Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run Effect hook only when both dependencies change

I have a React component that fetches data using the useEffect hook like so:

const cache = {key: "data-fetched-using-key"}
function Config({key, options}) {
    const [data, setData] = useState();
    useEffect(() => {
        const fetchedData; // fetch data using key and options
        setData(fetchedData);
        cache[key] = fetchedData;
    }, [key, options])
    return <p>{data}</p>;
}

This runs the hook every time key or options change. However, I'm also caching the data locally, and only want the effect to run when both key AND options change (since for each key/options combination the data will always be the same).

Is there a clean way to depend on the combination of key AND options rather than key OR options using React Hooks?

like image 267
vis Avatar asked Jul 04 '19 06:07

vis


People also ask

How do you run useEffect only when state changes?

Use the useEffect hook to listen for state changes in React. You can add the state variables you want to track to the hook's dependencies array and the logic in your useEffect hook will run every time the state variables change.

How do you make use effect run only once?

Side Effect Runs Only Once After Initial Render You can pass an empty array as the second argument to the useEffect hook to tackle this use case. useEffect(() => { // Side Effect }, []); In this case, the side effect runs only once after the initial render of the component.

Can a useEffect have multiple dependencies?

Multiple dependencies log(“This useEffect will run either data or siteUrl changes”, data, siteUrl); }, [data, siteUrl]); In the above scenario, useEffect will run when either value of 'data' or 'siteUrl' changes. We can also give more dependencies according to our requirements.

Does useEffect run after every update?

Does useEffect run after every render? Yes! By default, it runs both after the first render and after every update.


1 Answers

You can create this sort of logic with useRef(). Consider the following example and sandbox: https://codesandbox.io/s/react-hooks-useeffect-with-multiple-reqs-6ece5

const App = () => {
  const [name, setName] = useState();
  const [age, setAge] = useState();

  const previousValues = useRef({ name, age });

  useEffect(() => {
    if (
      previousValues.current.name !== name &&
      previousValues.current.age !== age
    ) {
      //your logic here
      console.log(name + " " + age);
      console.log(previousValues.current);

      //then update the previousValues to be the current values
      previousValues.current = { name, age };
    }
  });

  return (
    <div>
      <input
        placeholder="name"
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <input
        placeholder="age"
        value={age}
        onChange={e => setAge(e.target.value)}
      />
    </div>
  );
};

Workflow:

  1. We create a ref object for the two values we want to keep track of, in this case its a name and age. The ref object is previousValues.
  2. useEffect is defined but we do not provide it any dependencies. Instead, we just have it execute whenever there is a state-change to name or age.
  3. Now inside useEffect we have conditional logic to check whether the previous/initial values of both name and age are different than their corresponding state-values. If they are then good we execute our logic (console.log).
  4. Lastly after executing the logic, update the ref object (previousValues) to the current values (state).
like image 123
Chris Ngo Avatar answered Sep 20 '22 22:09

Chris Ngo