ref – https://stackoverflow.com/questions/72508690/what-is-the-effect-if-a-useeffect-listens-to-a-non-state-value-of-having-a-non
1) Your component will only re-render if a value of a state variable has changed (setState at or above)] or
2) props that is been passed to this is changed where the props passed have to be a state (else it won’t rerender)
Thus, only change in value of state or props in a component re-renders the component
Let’s take a look at an example for 1)
Any variable can go in the dependency array, state or not. And as long as it’s in the array and it changes, useEffect’s callback gets re-executed.
BUT!, how will useEffect notice that change?
It does a diff whenever the component re-renders. And only a state change with a setState can trigger a render/re-render
Say we have the below component. We should have Hello Word logged in the console when the component renders the first time, and every time rand changes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
export default function Comp() { let rand = Math.random(); // random decimal useEffect(() => { console.log("Hello Word"); }, [rand]); // when rand changes, we expect to log return ( <button onClick={() => { rand = Math.random() }}> New value </button> ); } |
Clicking on that button changes rand, but we won’t have a new log, because there isn’t any re-render as no state has changed, so useEffect didn’t do a diff, so it’s not aware of the change.
Let’s take this same component, and change it a little bit, as below. Now every time you click on the button the component re-renders, because we are setting a state with setState, and while re-rendering if the value of rand changes from the previous one, we will get a new log.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
export default function Comp() { const [state, setState] = useState(true); // new line added let rand = Math.random(); useEffect(() => { console.log("Hello Word"); }, [rand]); // notice that the click handler has changed return ( <button onClick={() => { rand = Math.random(); setState(!state); } }> New value </button> ); } |
Let’s take a look at an example for 2)
quickTickets is state.
We pass it via props into a functional component useEffectPublisher.
1 2 3 4 5 |
const [quickTickets, setQuickTickets] = useState<UITicketsModel[]>([]); useEffectPublisher({ quickTickets, }); |
When parent state quickTickets change, it will propogate it to its child useEffectPublisher, which uses it
in its dependency array. This causes useEffectPublisher to re-render which leads the dependency array to do a diff on quickTickets.
1 2 3 4 5 6 7 8 9 10 |
const useEffectPublisher = () => ({ quickTickets, }: aiBetSlipProps) => { useEffect(() => { // the effect }, [quickTickets]); return null; } }; |