Home > Enterprise >  React useEffect hook and eslint warning
React useEffect hook and eslint warning

Time:12-02

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 (
    ...
  );
}

Show code snippet

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>

}
  • Related