简体   繁体   中英

React: State is not up-to-date when I unmount component

In my job I have to make an http request when someone leaves the page. My idea was to do this request when the component of that page unmounts.

If I understand it correctly this can be done by putting logic in the return function of useEffect. When I do this it triggers at the right time, but the state values I want to use are not up-to-date. Is there a way to get up-to-date values?

      useEffect(() => {
    
        return () => {
    
          //this runs on unmount
         // but the state changes that happened are not registered it seems
        }
      }, [])

I have created a simple example in codesandbox: when you change the state from 4 to 8 and then hide the component. the NUM value in the unmount is still 4 (check console log). How can I get the current state value when I unmount the component?

https://codesandbox.io/live/b6e65d13114

https://codesandbox.io/s/loving-galois-okb0b (not sure which link to share is best)

You can use a React ref to cache a copy of the state to access in the cleanup function.

import { useEffect, useRef, useState } from "react";

export const NumCheck = () => {
  const [num, setNum] = useState(4);
  const stateRef = useRef(); // <-- ref to cache state value

  useEffect(() => {
    stateRef.current = num; // <-- cache state value on change
  }, [num]);

  useEffect(() => {
    return () => {
      console.log("NUM CHECK", stateRef.current); // <-- access cached state value
    };
  }, []);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>click the button to change number</h2>
      <button onClick={() => setNum(8)}>click me</button>

      <br />
      <br />
      <h5>{num}</h5>
    </div>
  );
};

编辑 react-state-is-not-up-to-date-when-i-unmount-component

Each time you show NumCheck component, num is assigned to 4 again.

I think you can solve your problem by sending the num state as a prop to the NumCheck component. With that no matter is NumCheck component is re-rendered again state of num is assigned to the parent component(in your case it will stay 8).

Numcheck component:

    import "./styles.css";
    import { useEffect, useState } from "react";
    
    export const NumCheck = ({ num, setNum }) => {
      useEffect(() => {
        return () => {
          console.log("NUM CHECK", num);
        };
      }, []);
    
      return (
        <div className="App">
          <h1>Hello CodeSandbox</h1>
          <h2>click the button to change number</h2>
          <button onClick={() => setNum(8)}>click me</button>
    
          <br />
          <br />
          <h5>{num}</h5>
        </div>
      );
    };

App component

export default function App() {
  const [show, setShow] = useState(true);
  const [num, setNum] = useState(4);
  return (
    <>
      {show ? (
        <div>
          <NumCheck num={num} setNum={setNum}  />
          <button onClick={() => setShow(!show)}>hide the component!</button>
        </div>
      ) : (
        <div>
          <h5>hidden</h5>
          <button onClick={() => setShow(!show)}>show the component!</button>
        </div>
      )}
    </>
  );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM