I’m looking for recommendations about how to solve the following problem:
I have a component A that has two states, state1 and state2.
If I want to run an effect only when state1 changes but in the useEFfect callback I use the value of state2, how can I solve the issue about array dependencies eslint react hooks warning ?
Ex.
function A() {
const [state1, setState1] = useState(0);
const [state2, setState2] = useState(0);
useEffect(() => {
const a = state1 state2;
// do some async logic using a
}, [state1]); //Here eslint react hooks rule requests adding state2 to the dependency array!
return <div> some text </div>
}
CodePudding user response:
The common method would typically be to disable the linting rule specifically for that line.
function A() {
const [state1, setState1] = useState(0);
const [state2, setState2] = useState(0);
useEffect(() => {
// do some async logic using a
const a = state1 state2;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [state1]);
return <div> some text </div>;
}
But the drawback here is it can mask dependency issues if the dependencies actually change and you forget to update the dependency array.
You can use a React ref and an additional useEffect
hook to cache a current state2
value and refer to this in the other useEffect
callback.
function A() {
const [state1, setState1] = useState(0);
const [state2, setState2] = useState(0);
const state2Ref = useRef(state2);
useEffect(() => {
state2Ref.current = state2;
}, [state2]);
useEffect(() => {
// do some async logic using a
const a = state1 state2Ref.current;
}, [state1]);
return (
...
);
}
function A() {
const [state1, setState1] = React.useState(0);
const [state2, setState2] = React.useState(0);
const state2Ref = React.useRef(state2);
React.useEffect(() => {
state2Ref.current = state2;
}, [state2]);
React.useEffect(() => {
// do some async logic using a
const a = state1 state2Ref.current;
console.log("effect called", a);
}, [state1]);
return (
<div>
some text
<div>
<button type="button" onClick={() => setState1((c) => c 1)}>
Update State 1
</button>
<button type="button" onClick={() => setState2((c) => c 1)}>
Update State 2
</button>
</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<A />,
rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root" />
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You need to add // eslint-disable-next-line react-hooks/exhaustive-deps
to your userEffect like this:
function A() {
const [state1, setState1] = useState(0);
const [state2, setState2] = useState(0);
useEffect(() => {
const a = state1 state2;
// do some async logic using a
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [state1]); //Here eslint react hooks rule requests adding state2 to the dependency array!
return <div> some text </div>
}