score:0

Accepted answer

It's not suprising - when You adding the values list in the dependency array, the useEffect will execute on every change of the value list - that leads to the infinite loop :)

According to the previous answer of @norbitrial, hiding of the error will not resolve the things, becuase every dependency from scope MUST be declared in the dependencies array, avoiding it can lead to unexpected behaviours.

I would recommend to consider using useReducer in this situation. It will cause that logic of modifications of the dependency array can be moved out of the useEffect hooks' scope - and You will be not forced to attach it as a dependency of useEffect.

score:1

Ideally, you would add some condition/check to see if values already has the value that you want. As setValues appears to be called on every render, which triggers a re-render, times infinity.

Potentially, using something like Lodash's isEqual combined with Lodash's orderBy would do this trick (because sort will mutate the original array).

  const [ascValue, setAscValue] = useState(true);
  const [values, setValues] = useState([
    { id: 10 },
    { id: 5 },
    { id: 12 },
    { id: 1 },
    { id: 2 },
    { id: 900 },
    { id: 602 }
  ]);

  useEffect(() => {
    function sortValues() {
      const sorter = ascValue ? "asc" : "desc";
      if (!_.isEqual(values, _.orderBy(values, ["id"], [sorter]))) {
        console.log("logged");
        setValues(() => _.orderBy(values, ["id"], [sorter]));
      }
    }

    sortValues();
  }, [ascValue, values]);

The point is, useEffect shouldn't set state every on every render by default (it can once render has finished and the user triggers an action).

A fork of your CodeSandbox to demonstrate that the side effect should only update the components state if the condition is met.

score:2

I don't see any issues with your code. What I would do is just simply ignore the warning by adding // eslint-disable-next-line react-hooks/exhaustive-deps as the following:

useEffect(() => {
    function sortValues() {
      let sorted;
      const array = [...values];
      if (ascValue) {
        sorted = array.sort((a, b) => a - b);
      } else {
        sorted = array.sort((a, b) => b - a);
      }

      setValues(sorted);
    }

    sortValues();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ascValue]);

Maybe one shortening on sortValues():

function sortValues() {
    const compare = ascValue ? (a, b) => a - b : (a, b) => b - a;
    setValues([...values].sort(compare));
}

I hope that helps!


Related Query

More Query from same tag