question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItĀ collects links to all the places you might be looking at while hunting down a tough bug.

And, if youā€™re still stuck at the end, weā€™re happy to hop on a call to see how we can help out.

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

https://codesandbox.io/s/happy-dubinsky-91lhc?eslint=1&expanddevtools=1&module=%2Fsrc%2FFormMemory.jsx

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:closed
  • Created 4 years ago
  • Comments:25 (13 by maintainers)

github_iconTop GitHub Comments

2reactions
jaredpalmercommented, Jul 14, 2019

I think I need to think thru this more

2reactions
johnromcommented, Jul 14, 2019

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.

const { setFieldValue, setFieldTouched } = useFormikContext()
const setField = React.useCallback((field, value) => {
  setFieldValue(field, value)
  setFieldTouched(field, true)
}, [setFieldValue, setFieldTouched])

I am not against the idea of splitting formikContext into formik and formikState where formikState is a snapshot and formik.currentState would be the live state. I think this would be super helpful for async operations.

Read more comments on GitHub >

github_iconTop Results From Across the Web

useEffect exhaustive-deps warning: what possible issues is ...
I think the biggest gotcha with class life cycle methods like componentDidMount is that we tend to think of it as an isolated...
Read more >
Understanding the React exhaustive-deps linting warning
The obvious answer is to add the count variable to the dependency array. In VS Code, with the ESlint extension, and in other...
Read more >
React.useEffect Hook ā€“ Common Problems and How to Fix ...
React Hook useEffect has a missing dependency: 'user'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps).
Read more >
Successfully using async functions in React useEffect
How to avoid the exhaustive deps ESLint error by properly using JavaScript async functions within the React useEffect Hook.
Read more >
A Complete Guide to useEffect - Overreacted
Do I need to specify functions as effect dependencies or not? ... Then React updates the DOM to match our latest render output....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found