After updating React to 16.13, I am receiving this error, which is pretty cryptic and only occurs on that update (16.12 works fine)
Demo can be found here:
https://github.com/LXSMNSYC/react-scoped-model/tree/master/example
I have this issue too. @LXSMNSYC what was the solution?
@samparnell apparently when I encountered this "problem", I wasn't aware about the changelogs, and so I read it and at the very beginning of the logs: https://reactjs.org/blog/2020/02/26/react-v16.13.0.html, the warning is indicated there.
TL;DR don't synchronously call setState
inside other functional components, defer the call to useEffect
.
Something like this yields a warning:
function Child({ setState }) {
setState(true);
return <h1>This is a child.</h1>;
}
function Parent() {
const [state, setState] = useState(false);
return <Child setState={setState} />;
}
so it should be:
function Child({ setState }) {
useEffect(() => {
setState(true);
}, [setState]);
return <h1>This is a child.</h1>;
}
Yeah I have similar issue on a project
What about a setState used in a callback in a child like :
function Child({ callback }) {
return <button onClick={callback}>This is a child.</button>;
}
function Parent() {
const [state, setState] = useState(false);
const callback = useCallback(() => {
setState(true);
}, []);
return <Child callback={callback} />;
}
Is there a way to avoid raising the warning in this case ?
@minirom You're not calling callback
during render but in an event handler. This doesn't seem to cause any issues
@eps1lon in my case it does (in my project), so I am a little bit confused.
there are a lot of callback like this, I will try to investigate it more and create a new issue when I understand why I have this warning raised with the callbacks
@eps1lon in my case it does (in my project), so I am a little bit confused.
Me as well since the code you posted did not do what you're describing.
Nice one ! with that exchange I found a callback directly called in the component
I did not noticed that before
Thanks ;)
I seem to be hitting a similar issue to @minirom - I am trying to do this from a callback and hit this error. I have a component that is my parent, wrapping Antd's Select component. Here is quick code sandbox to illustrate.
This seems to be the parent calling a child with an event handler scenario, and it still throws that warning. @eps1lon you seemed to think this shouldn't be an issue, so I am sure I am missing something the way my code is structured. Would love your thoughts. Thanks!
Is there another way to get rid of this warning when you don't have the possibility of wrapping the trigger in a useEffect? For example I am using an external library that has an onChange
callback prop, that I implement and call setState
in. This external library calls the onChange
somewhere in the render cycle (componentWillMount
), which in turn causes the warning in my app. What would be the way to fix this in this external class component or in my application?
Is there another way to get rid of this warning when you don't have the possibility of wrapping the trigger in a useEffect? For example I am using an external library that has an
onChange
callback prop, that I implement and callsetState
in. This external library calls theonChange
somewhere in the render cycle (componentWillMount
), which in turn causes the warning in my app. What would be the way to fix this in this external class component or in my application?
The same issue has been submitted to that external library. Await some fix and hope for it to solve your problem 馃榿 Meanwhile, I think you could defer the setState by means of scheduling i.e. Promise.resolve()
@LXSMNSYC thanks! I'll give it a try!
@LXSMNSYC for now I found a workaround by putting my state update in a setTimeout(() => ..)
, and I'll wait for the fix. Thanks!
I get this warning for every useHover
hook implementation I can find, including ones that are using useCallback
or useEffect
- which I understand should avoid this warning:
execute callback , window.addEventListener, history api , etc, inside "useEffect" hook
閭f垜鐢‥S6绫荤粍浠跺啓鐨勬椂鍊欎篃浼氬嚭鐜拌繖涓棶棰橈紝璀﹀憡鍜屼綘浠鐨勪竴妯′竴鏍凤紝鐜板湪闂瑙e喅浜嗗悧
If anyone is following this thread, I have had to do this lots of times in React...
Using redux, etc. by passing the callback function from the parent...
You don't get the error you are talking about because it's the child which ends up running the function, but it is still encapsulated from the parent.
// PARENT COMPONENT which passes AccountList to Semantic Cards
const globalData = useSelector(state => state.appdata)
const dispatch = useDispatch();
<AccountList
accounts={accounts}
// THIS IS WHERE I PASS THE CALLBACK FROM THE PARENT (WITH the redux stuff needed to dispatch actions)
initAccount={(account) => initAccount(globalData, dispatch, Creators, account)
}
/>
//
// AccountList
const mapAccounts = (accounts, initAccount) => {
console.log(initAccount)
return (
accounts.map(account => {
return {
as: Link,
to: '/storePage/',
// This onclick is what creates the route change (and note that it sends in what has changed (the accountID.))
// further note that in the parent I need the dispatch, Creators, and globalData (my state), but only need to pass the account as they are already in the function
onClick: () => initAccount(account.accountID),
state: { accountID: account.accountID },
childKey: account.accountID,
header: 'Account: '+account.accountID,
meta: <Card.Meta style={{color: 'dimgray'}} state={{ accountID: account.accountID, siteTitle: account.siteTitle }}>{12.99}</Card.Meta>,
}
})
)
}
// THIS IS WHERE I SENT THE paramaters in (from the parent... Note it maps through and sends the
function to the onClick above...)
export default ({accounts, initAccount}) => (
<Card.Group items={mapAccounts(accounts, initAccount)} itemsPerRow={1} stackable />
)
For everyone on this thread, I had this issue and fixed it by following someone's suggestion of adding key to the Picker. That solved the problem for me, all is working great. I used the value from list which is unique. See below:
onValueChange={value => handleSelectStuff(value)}
placeholder={{ label: 'Select Stuff' }}
items={gStuffList}
style={pickerSelectStyles}
pickerProps={styles.rnPickerProps}
useNativeAndroidPickerStyle={false}
value={gStuffID}
/>
I have this issue when updating global state through a redux setter-action from function body of one component to subscriber-component on a different screen, to change 2 sibling components on different screens (React Native). And this innovation in React 13 really sucks, as it breaks the whole pattern of updation. React really started to suck, guys. And no matter what I tried to do - useEffect, etc., this problem persists now after upgrade. IMHO, setting globally state through redux for sibling components should not be an issue. Finally, React is shooting itself in the feet... Back to the previous version is the only solution for now. But what is the future of this, anyways?..
I have this issue when updating global state through a redux setter-action from function body of one component to subscriber-component on a different screen, to change 2 sibling components on different screens (React Native). And this innovation in React 13 really sucks, as it breaks the whole pattern of updation. React really started to suck, guys. And no matter what I tried to do - useEffect, etc., this problem persists now after upgrade. IMHO, setting globally state through redux for sibling components should not be an issue. Finally, React is shooting itself in the feet... Back to the previous version is the only solution for now. But what is the future of this, anyways?..
You might be confused. This problem only arises in the user-land. The problem does not occur in React, the problem occurs in your implementation.
Most helpful comment
@samparnell apparently when I encountered this "problem", I wasn't aware about the changelogs, and so I read it and at the very beginning of the logs: https://reactjs.org/blog/2020/02/26/react-v16.13.0.html, the warning is indicated there.
TL;DR don't synchronously call
setState
inside other functional components, defer the call touseEffect
.Something like this yields a warning:
so it should be: