I have trouble debugging this code.
I have an App component:
function App() {
const [state, setState] = useState(0);
const onSelectItem = () => {
console.log("🐞: onSelectItem -> currentState", state);
};
// items is an array of ReactNode: button, when click on it. It will log the currentState.
const items = ["FirstItem", "SecondItem"].map(item => (
<button key={item} onClick={() => onSelectItem()}>
{item}
</button>
);
);
return (
<div className="App">
<Menu items={items} />
<hr />
<button onClick={() => setState(prevState => prevState + 1)}>Change State</button>
</div>
);
}
My Menu
components will receive items
prop, and render it. It also has ability to set the active item. For simplicity's sake, I render a button
to set activeItem to the first one. The active item will also be rendered.
function Menu({ items }) {
const [activeItem, setActiveItem] = useState(items[0]);
return (
<div>
{items}
<hr />
{activeItem}
</div>
);
}
Now, come to the main part:
hr
) => it shows currentState (OK)hr
) => it shows currentState (OK)hr
) => It shows currentState is 1 (OK)hr
) => It still shows 0 (which is the last state) (???) My guess is React keeps remembering everything when using useState
. But I'm not sure. Could anyone explain this for me!
I also include the snippets for you to easily understand my problem.
const {useState} = React; function Menu({ items }) { const [activeItem, setActiveItem] = useState(items[0]); return ( <div> {items} <hr /> <span>Active Item:</span> {activeItem} </div> ); } function App() { const [state, setState] = useState(0); console.log(state); const onSelectItem = () => { console.log("🐞: onSelectItem -> currentState", state); }; const items = ["FirstItem", "SecondItem"].map(item => { return ( <button key={item} onClick={() => onSelectItem()}> {item} </button> ); }); return ( <div className="App"> <Menu items={items} /> <hr /> <button onClick={() => setState(prevState => prevState + 1)}>Change State</button> </div> ); } ReactDOM.render(<App />, document.getElementById('app'));
<div id="app"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="react"></div>
You are trying to access the state from App component in your Menu component.
State is local to that component and can't be accessed outside, if you would like to access the state outside the component you can refer to the useContext hook implementation.
https://reactjs.org/docs/hooks-reference.html#usecontext
Reason you are seeing 0 in the Active state is that is the default value of useState.
You need to pass key to your menu component.
Whenever there is change in props, the component has to re-render with new props.
Refer this artcile from their official docs - https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrolled-component-with-a-key
Change I made is passing state as key to Menu component
const {useState} = React; function Menu({ items }) { const [activeItem, setActiveItem] = useState(items[0]); return ( <div> {items} <hr /> <span>Active Item:</span> {activeItem} </div> ); } function App() { const [state, setState] = useState(0); console.log(state); const onSelectItem = () => { console.log("🐞: onSelectItem -> currentState", state); }; const items = ["FirstItem", "SecondItem"].map(item => { return ( <button key={item} onClick={() => onSelectItem()}> {item} </button> ); }); return ( <div className="App"> <Menu items={items} key={state}/> <hr /> <button onClick={() => setState(prevState => prevState + 1)}>Change State</button> </div> ); } ReactDOM.render(<App />, document.getElementById('app'));
<div id="app"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="react"></div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.