skip to Main Content

Here in my React the clean up function is not executed when re-rendering:

import React, { useRef, useState } from 'react';

export default function App() {
  const [x, setX] = useState(2);
  const d = useRef(null);

  return (
    <>
      <p ref={(node) => {
        console.log('start');
        return () => {
          console.log('finish');
        };
      }}>{x}</p>
      <button onClick={() => setX(x + 1)}>hello</button>
    </>
  );
}

i want my clean up function to be executed when the ref callback is updated hence here the callback is created every render then the clean up must be executed every render!

2

Answers


  1. React refs don’t have a cleanup function in the same way the useEffect hook callback returns a cleanup function. React refs that are set with the callback syntax are simply just called again and passed null.

    Example:

    function App() {
      const [x, setX] = React.useState(2);
    
      return (
        <div className="App">
          <span
            ref={(node) => {
              if (node) {
                console.log("start", node);
              } else {
                console.log("finish", node);
              }
            }}
          >
            {x}
          </span>{" "}
          <button onClick={() => setX((x) => x + 1)}>+</button>
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    const root = ReactDOM.createRoot(rootElement);
    
    root.render(<App />);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
    <div id="root" />

    In the ref callback, check when the ref is null and handle any "cleanup" duties.

    Note: It’s more conventional/standard to use a useEffect hook to run any cleanup logic.

    function App() {
      const [x, setX] = React.useState(2);
    
      React.useEffect(() => {
        console.log("start");
        return () => {
          console.log("finish");
        };
      }, [x]);
    
      return (
        <div className="App">
          <span>
            {x}
          </span>{" "}
          <button onClick={() => setX((x) => x + 1)}>+</button>
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    const root = ReactDOM.createRoot(rootElement);
    
    root.render(<App />);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
    <div id="root" />
    Login or Signup to reply.
  2. Ref cleanups are only available in canary builds of React, so currently not available in stable versions, if you want to play around with it, you need to use a canary build for the time being, or test for null like Drew suggests in his answer:

    function App() {
      const [x, setX] = React.useState(2);
    
       return (
          <React.Fragment>
            <p ref={(node) => {
              console.log('start', node);
              return () => {
                console.log('finish', node);
              };
            }}>{x}</p>
            <button onClick={() => setX(x + 1)}>hello</button>
          </React.Fragment>
      );
    }
    
    
    const root = ReactDOM.createRoot(document.body);
    
    root.render(<App />);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.0-canary-c3048aab4-20240326/umd/react.development.min.js" integrity="sha512-N3bJHd0IQK3T+qeOxAxW+CC1/dYPREk4z6UvuqDrbk1DcK173oFL2RjSDwS1F5nLMaPwI3v4yWXCtuf2rYw3/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.0-canary-c3048aab4-20240326/umd/react-dom.development.min.js" integrity="sha512-36i1/IQRwia35jjTQr9i7Hsb/CaU8B5I0CL6/JMnOO7XExnCKXhsNR14c15DhSswOvN7KpH6qYAoCiJVvn3QBw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search