1

I thought I understand everything about React by now, but I can't make this simple use case work. I need to run a function when the component unmounts, to tell another system, that an announced data update can be discarded.

My approach was to useEffect with an empty dependency array, which works, but is wrong according to ESLint and the React docs.

Approach 1: Don't add the reactive value (input) to the dependency array

This works, but according to the React Docs is wrong and will introduce bugs.

Approach 2: Add the reactive value to the dependency array

This won't work, since the clean-up function will run every time the value changes, not just when the component unmounts.

import { useEffect, useState } from "react";

function MyComponent({ updateId }: { updateId: string }) {
  const [input, setInput] = useState("");

  useEffect(() => {
    return () => {
      // This should only run when the component unmounts, but must access the input value
      if (input === "") {
        // discard update
      }
      // For this example just print the value
      console.log(input);
    };
  }, []);

  return <input value={input} onChange={(e) => setInput(e.target.value)} />;
}

What is the solution for this problem? I found another question concerning this on StackOverflow which suggested a workaround using useRef, but this seems also hacky. There has to be a simple way for this trivial requirement. In Svelte I would just use the onDestroy lifecycle function.

Ruudy
  • 217
  • 1
  • 4
  • 17
  • Just out of curiosity, what is the trigger for your component unmounting? – Jacob Smit Jul 09 '23 at 21:18
  • In this case the user could navigate to another page (back button, menu etc.). But I want to know what the agnostic solution is to this problem in React. – Ruudy Jul 09 '23 at 21:33
  • In the code you've shown `input` will always be an empty string when tested in the unmount function. Changes to `input` won't affect the effect because you didn't specify it in the dependency array. So what's she point of checking the value? – Konrad Jul 09 '23 at 22:09
  • True, so both options don't work. Do you know a solution? – Ruudy Jul 10 '23 at 00:04
  • Take a look https://stackoverflow.com/questions/60456803/how-to-access-state-when-component-unmount-with-react-hooks – Konrad Jul 10 '23 at 07:00
  • `useRef` is not a hacky solution, but a valid way to store and access mutable values across renders. React does not provide a built-in way to run a function on unmount with a dependency, because it follows the principle of consistency. – Pluto Jul 10 '23 at 07:31
  • @VictorL. "because it follows the principle of consistency" can you elaborate on this part? So the`useRef` way is valid and also consistent? – Ruudy Jul 10 '23 at 16:10
  • Sure, I can elaborate. The principle of consistency means that React follows some rules and patterns that make it easier to reason about how it works and what to expect from it. For example, React always re-renders a component when its props or state change, and always calls the effect functions after every render. This makes it consistent with how React works with state and props. – Pluto Jul 10 '23 at 16:29
  • The `useRef` way is valid because it lets you store a mutable value that doesn't affect the rendering of the component. It is also consistent because it doesn't break any of the rules or patterns that React follows. You can still use props, state, and effects as usual, and useRef will not interfere with them. – Pluto Jul 10 '23 at 16:29
  • Alright, thanks for the explanation and help! – Ruudy Jul 11 '23 at 19:27

0 Answers0