React hooks question (or bug report?)
See original GitHub issueHeyyyy team,
Howās everyone doing? š
I was trying out React hooks and was rewriting one of my side project but a buggy issue caught me. I created a repro case here.
The case is:
function App() {
let store = {};
const [authStatus, updateAuthStatus] = useState(false);
useEffect(() => {
asyncHelper().then(() => {
store = {
nested: {
value: 'Hello World',
},
}
// people will naturally believe store is updated when auth status is true
// but it's actually not
updateAuthStatus(true);
});
}, []);
if (!authStatus) {
return <h1>Loading...</h1>
}
return (
// will throw an error here (store hasn't been updated)
<h1>{store.nested.value}</h1>
);
}
Iām casting/updating a new value to store
in useEffect
, assuming that it works similarly with cDM
, and then update the authStatus
. But the last line when it tries to render <h1>{store.nested.value}</h1>
, itāll throw the error ācannot read value of undefinedā because store hasnāt been updated this time.
Itās very natural to have this operation sequence in mind:
- render the loading state
- run useEffect
- store gets updated
- auth status gets updated
- render the correct value
However it works as expected if I also wrap the store
with a local state:
function App() {
const [store, updateStore] = useState({});
const [authStatus, updateAuthStatus] = useState(false);
useEffect(() => {
asyncHelper().then(() => {
updateStore({
nested: {
value: 'Hello World',
},
})
updateAuthStatus(true);
});
}, []);
if (!authStatus) {
return <h1>Loading...</h1>
}
return (
// will throw an error here (store hasn't been updated)
<h1>{store.nested.value}</h1>
);
}
Iām guessing maybe itās because the async nature of the state update function but not sure if I missed something here or itās a bug.
Have fun in React Conf! Iām so excited that weāre finally SHIPPING things! š
Issue Analytics
- State:
- Created 5 years ago
- Reactions:1
- Comments:5 (4 by maintainers)
Yeah, if you want to compare it to class components the equivalent would be doing
The thing is, a function componentās body is executed every render, while
componentDidMount
is only executed on mount, so yes, Iād say this is definitely expected behaviour.Itās not a breaking change because you can still use class components with
componentDidMount
just fine.