Mehran Motiee
Mehran Motiee

Reputation: 3947

react when use useeffect for unmount , data not change

i use this code in my react project when change data1 with usestate , i see data1 is change to 1 but when unmount component data1 is default value 0 . whats wrong? code is:

useEffect( () => console.log( ["mount",data1] ), [] );
useEffect( () => console.log( ["will update",data1] ) );
useEffect( () => () => console.log( ["unmount",data1] ), [] );

log when mount and change is:

["mount", "0"]
["will update", "0"]
["will update", "2"]
["unmount", "0"]

Upvotes: 1

Views: 4385

Answers (2)

Mehran Motiee
Mehran Motiee

Reputation: 3947

i finaly use this function for get last data when unmount

thanks from "nima arefi" for write it

const useTaskBeforeUnmount = ( calback, ...data ) => {
        const mounted = React.useRef( null );

        React.useEffect( () => {
            mounted.current = true;
            return () => {
                mounted.current = false;
            };
        }, [] );

        React.useEffect(
            () => () => {
                if ( !mounted.current ) {
                    calback( { ...data } );
                }
            },
            [ calback, ...data ],
        );
    };

then use it in my component like this

useTaskBeforeUnmount( console.log, data1, data2, data3 );

Upvotes: 2

Shubham Khatri
Shubham Khatri

Reputation: 281726

When you define your effect like

useEffect( () => () => console.log( ["unmount",data1] ), [] );

You essentially tell it to run on initial render and hence the data1 that the callback points to is the initial value that it inherited from the closure and is never updated since the function is no longer initialised

If at all, for any reason you want the data1 to be accessible in useEffect you must pass it as the second argument to useEffect

useEffect( () => () => console.log( ["unmount",data1] ), [data1] );

In such a case the effect will be cleaned up any change of data1

You could also make use of useRef to store the data and access it in unmount.

function App() {
  const [data1, setData1] = useState(0);
  const refAttr = useRef();
  useEffect(
    () => () => {
      console.log("unmount", refAttr.current);
    },
    []
  );
  useEffect(() => {
    setInterval(() => {
      setData1(data1 => {
        refAttr.current = data1 + 1;
        return data1 + 1;
      });
    }, 1000);
  }, []);
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

Working demo

Upvotes: 4

Related Questions