Reputation: 36876
I want to understand 3 cases of "why" about useEffect and eslint and overall "how" about how useEffect define when to trigger.
Questions is inside code example as comments.
import React, { useEffect, useState, useCallback } from "react";
import ReactDOM from "react-dom";
function App() {
// Case A
// why eslint want a as dependensy if it works fine?
const [a, setA] = useState(0);
const [triggerA, setTriggerA] = useState(true);
useEffect(() => {
console.log("Case 1: useEffect a: " + a);
}, [triggerA]);
// Case B
// why eslint want fnB as dependensy if it works fine?
const [b, setB] = useState(0);
const [triggerB, setTriggerB] = useState(true);
const fnB = useCallback(() => {
console.log("Case B: useCallback fnB b: " + b);
}, [b]);
useEffect(() => {
fnB();
}, [triggerB]);
// Case C
// why adding fnC function as dependensy trigger useEffect,
// but adding setC is not?
// how useEffect understand when to trigger?
const [c, setC] = useState(0);
const [triggerC, setTriggerC] = useState(true);
const fnC = useCallback(() => {
console.log("Case C: useCallback fnC c: " + c);
}, [c]);
// no trigger
useEffect(() => {
console.log("no triger");
fnC();
setC((v) => {
console.log("useEffect setC: " + v);
return v;
});
}, [setC]);
// triger
useEffect(() => {
console.log("triger");
fnC();
setC((v) => {
console.log("useEffect fnC: " + v);
return v;
});
}, [fnC]);
console.log("----");
return (
<>
<button onClick={() => setA((v) => v + 1)}>Add 1 to A</button>
<button onClick={() => setTriggerA((v) => !v)}>Trigger A</button>
<div>A: {a}</div>
<hr />
<button onClick={() => setB((v) => v + 1)}>Add 1 to B</button>
<button onClick={() => setTriggerB((v) => !v)}>Trigger B</button>
<div>B: {b}</div>
<hr />
<button onClick={() => setC((v) => v + 1)}>Add 1 to C</button>
<button onClick={() => setTriggerC((v) => !v)}>Trigger C</button>
<div>C: {c}</div>
<hr />
</>
);
}
ReactDOM.render(<App />, document.querySelector("#root"));
Upvotes: 0
Views: 607
Reputation: 4938
Dependency array is an array of dependencies that, when changed from the previous render, will recall the effect function defined in the first argument.
In short, whatever variables and functions you're using inside the effect function should be inside your dependency array since the function depends upon them, it should re-rerun when either of the values changes.
a
inside your useEffect.fnB
inside your useEffect.fnC
in your dependency array.setC
is a state updater function from useState
and the reference to it never changes unless done manually.All your function will work even if you don't define your dependencies or miss some of the dependency, the only problem being the effect will not be re-rerun if either the value changes which will lead to many bugs. For example :-
const id = props.id;
const [idData, setIdData] = React.useEffect(null);
// doesn't run when id changes
React.useEffect(() => {
async function callApiAndUpdateIdData {
}
callApiAndUpdateIdData()
}, []);
// runs when id changes
React.useEffect(() => {
async function callApiAndUpdateIdData {
}
callApiAndUpdateIdData()
}, [id]);
Upvotes: 1