Major gotcha with react/exhaustive-deps
See original GitHub issueš Bug report / Feature request
Build forms in React, without the tears š
Today, I criedā¦
Current Behavior
Consider the following contrived example. The ESLint rule react/exhaustive-deps
immediately complains that formik
needs to be in deps. Makes sense, why not? Ouch! Such callback will be recreated on every little change because useFormikContext
always returns a new object.
const formik = useFormikContext()
const setField = React.useCallback(field, value => {
formik.setFieldValue(field, value)
formik.setFieldTouched(field, true)
}, [formik])
The callback alone wouldnāt be too bad. But then comes useEffect
into play and things get very bad. The ESLint will once again suggest adding callback setField
to deps. Originally the effect that is supposed to be executed once (on mount) is now executed on every little change.
React.useEffect(() => {
readFieldMemory('name').then(memory => {
setField('name', memory)
})
}, [setField])
Lines of thinking here are like: āI have it wrapped in the callback, itās safe to have effect depend on it, right? Damnā¦ā
Expected behavior
I am aware I can disable ESLint for that particular line and avoid adding that dependency there. Thatās not the point. Anyone can get burned by it because itās a good assumption it will work just fine.
Reproducible example
Notice it grows geometrically for some reason and might kill your browser tab. But there is a button to actually start it, so donāt worry to open and check the code first.
Suggested solution(s)
This is really tricky. One side of a problem is that recreating a new object will allow Context to re-render interested parties. With stable reference, no render would happen.
So I am thinking something along the lines of splitting state and api object and providing two hooks for accessing each. The api object can have a stable reference while state can still cause necessary re-render. And ESLint suggestions wonāt be a problem anymore.
Issue Analytics
- State:
- Created 4 years ago
- Comments:25 (13 by maintainers)
Top GitHub Comments
I think I need to think thru this more
I donāt have a chance to confirm this theory works right now, but if setFieldValue and setFieldTouched are useCallbackād correctly, it should help to depend on those callbacks instead.
I am not against the idea of splitting formikContext into
formik
andformikState
whereformikState
is a snapshot andformik.currentState
would be the live state. I think this would be super helpful for async operations.