I am in the process of learning React, where I'm trying make a dropdown menu, where you can select different options. When you select an option, the corresponding data is supposed to be lifted to App.js, which I have done using useState() and props.
Unfortunfately, when clicking on the div with the onClick-function, the App freezes because of it infinitely refreshing the App.js view.
I have tested it quite a lot, and searched far and wide, but I can't seem to find a solution. When I moved the state from App.js to Header.js, I could make it work, but I need it lifted to App.js since I need to access it in other components.
I've provided the most relevant parts below.
App.js
const [summary, setSummary] = useState(undefined);
return (
<>
<Header user={user} setUser={setUser} auth={auth} provider={provider} summaries={summaries} current={summary} setSummary={setSummary} />
<main className="bg-light">
<Router>
<Switch>
<Route path="/" element={<Dashboard />} />
</Switch>
</Router>
</main>
</>
);
Header.js
function Header(props) {
return (
<header className="border-bottom border-black bg-white py-3">
<div className="container">
<div className="d-flex align-items-center justify-content-between">
<img src={Logo}></img>
{props.summaries ? <Dropdown items={props.summaries} current={props.current} setSummary={props.setSummary} /> : ''}
<div>{props.user ? props.user.displayName : 'Log venligst ind'}</div>
{props.user ? <Logout auth={props.auth} setUser={props.setUser} /> : <Login user={props.user} setUser={props.setUser} auth={props.auth} provider={props.provider} /> }
</div>
</div>
</header>
);
}
export default Header;
Dropdown.js
function Dropdown(props) {
const [dropdown, setDropdown] = useState(false);
const [selectedItem, setSelectedItem] = useState(undefined);
const [selectedSubItem, setSelectedSubItem] = useState(undefined);
const toggleOpen = () => setDropdown(!dropdown);
return (
<div className="dropdown">
{/* {props.items.map((summary) => JSON.stringify(summary) '<br><br>')} */}
<button className="btn btn-light-blue dropdown-toggle border-none" onClick={toggleOpen}>
{props.current ? props.current.name : 'Vælg'}
</button>
<div className={`dropdown-menu ${dropdown ? 'show' : ''}`} aria-labelledby="dropdownMenuButton">
<div className='row'>
<div className='col-4'>{props.items.map((summary) => <Item item={summary} selectItem={setSelectedItem} reset={setSelectedSubItem} key={summary.id} />)}</div>
<div className='col-4'>{selectedItem ? selectedItem.webProperties.map((subitem) => <Item item={subitem} setSummary={props.setSummary} selectItem={setSelectedSubItem} key={subitem.id} />) : ''}</div>
<div className='col-4'>{selectedSubItem ? selectedSubItem.profiles.map((subitem) => <Item item={subitem} setSummary={props.setSummary} key={subitem.id} />) : ''}</div>
</div>
</div>
</div>
);
}
export default Dropdown;
Item.js
function Item(props) {
return (
<div className="dropdown-item d-flex">
<div onClick={props.selectItem ? () => {props.selectItem(props.item); if (props.reset) props.reset(undefined)} : undefined}>{props.item.name}</div>
{props.setSummary ? <div className="btn btn-primary" onClick={() => props.setSummary(props.item)}>Vælg</div> : ''}
</div>
);
}
export default Item;
CodePudding user response:
props.setSummary()
does not exist since you are passing that setState handler through a prop labeled new={props.setSummary}
.
CodePudding user response:
function Header(props)
{
return <Dropdown {...props} />
}
function Dropdown(props)
{
return <Item key={subitem.id} {...props} />
}
function Item(props)
{
console.log(props);
return <div onClick={() => props.setSummary(props.key)}>Select</div>
}
Because of your passing props is not have the value of item
. You've passed the value is key
. Please check with console.log for every child element declaration. so you can avoid this kind of errors