Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. Read the Motivation to learn why we're introducing Hooks to React.
To update the state, call the state updater function with the new state setState(newState) . Alternatively, if you need to update the state based on the previous state, supply a callback function setState(prevState => newState) .
Use the useEffect hook to listen for state changes in React. You can add the state variables you want to track to the hook's dependencies array and the logic in your useEffect hook will run every time the state variables change.
In the useEffect , we are updating the useRef current value each time the inputValue is updated by entering text into the input field.
Generally speaking, using setState
inside useEffect
will create an infinite loop that most likely you don't want to cause. There are a couple of exceptions to that rule which I will get into later.
useEffect
is called after each render and when setState
is used inside of it, it will cause the component to re-render which will call useEffect
and so on and so on.
One of the popular cases that using useState
inside of useEffect
will not cause an infinite loop is when you pass an empty array as a second argument to useEffect
like useEffect(() => {....}, [])
which means that the effect function should be called once: after the first mount/render only. This is used widely when you're doing data fetching in a component and you want to save the request data in the component's state.
For future purposes, this may help too:
It's ok to use setState in useEffect
you just need to have attention as described already to not create a loop.
But it's not the only problem that may occur. See below:
Imagine that you have a component Comp
that receives props
from parent and according to a props
change you want to set Comp
's state. For some reason, you need to change for each prop in a different useEffect
:
DO NOT DO THIS
useEffect(() => {
setState({ ...state, a: props.a });
}, [props.a]);
useEffect(() => {
setState({ ...state, b: props.b });
}, [props.b]);
It may never change the state of a as you can see in this example: https://codesandbox.io/s/confident-lederberg-dtx7w
The reason why this happen in this example it's because both useEffects run in the same react cycle when you change both prop.a
and prop.b
so the value of {...state}
when you do setState
are exactly the same in both useEffect
because they are in the same context. When you run the second setState
it will replace the first setState
.
DO THIS INSTEAD
The solution for this problem is basically call setState
like this:
useEffect(() => {
setState(state => ({ ...state, a: props.a }));
}, [props.a]);
useEffect(() => {
setState(state => ({ ...state, b: props.b }));
}, [props.b]);
Check the solution here: https://codesandbox.io/s/mutable-surf-nynlx
Now, you always receive the most updated and correct value of the state when you proceed with the setState
.
I hope this helps someone!
Effects are always executed after the render phase is completed even if you setState inside the one effect, another effect will read the updated state and take action on it only after the render phase.
Having said that its probably better to take both actions in the same effect unless there is a possibility that b
can change due to reasons other than changing a
in which case too you would want to execute the same logic
useEffect
can hook on a certain prop or state. so, the thing you need to do to avoid infinite loop hook is binding some variable or state to effect
For Example:
useEffect(myeffectCallback, [])
above effect will fire only once the component has rendered. this is similar to componentDidMount
lifecycle
const [something, setSomething] = withState(0)
const [myState, setMyState] = withState(0)
useEffect(() => {
setSomething(0)
}, myState)
above effect will fire only my state has changed this is similar to componentDidUpdate
except not every changing state will fire it.
You can read more detail though this link
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With