How To Access State When Component Unmount With React Hooks?
Solution 1:
useState()
is a specialized form of useReducer()
, so you can substitute a full reducer to get the current state and get around the closure problem.
NoteEditor
importReact, { useEffect, useReducer } from"react";
functionreducer(state, action) {
switch (action.type) {
case"set":
return action.payload;
case"unMount":
console.log("This note has been closed: " + state); // This note has been closed: 201break;
default:
thrownewError();
}
}
functionNoteEditor({ initialNoteId }) {
const [noteId, dispatch] = useReducer(reducer, initialNoteId);
useEffect(functionlogBeforeUnMount() {
return() =>dispatch({ type: "unMount" });
}, []);
useEffect(functionchangeIdSideEffect() {
setTimeout(() => {
dispatch({ type: "set", payload: noteId + 1 });
}, 1000);
}, []);
return<div>{noteId}</div>;
}
exportdefaultNoteEditor;
App
importReact, { useState, useEffect } from"react";
import"./styles.css";
importNoteEditorfrom"./note-editor";
exportdefaultfunctionApp() {
const [notes, setNotes] = useState([100, 200, 300]);
useEffect(functionremoveNote() {
setTimeout(() => {
setNotes([100, 300]);
}, 2000);
}, []);
return (
<divclassName="App"><h1>Hello CodeSandbox</h1><h2>Start editing to see some magic happen!</h2>
{notes.map(note => (
<NoteEditorkey={`Note${note}`} initialNoteId={note} />
))}
</div>
);
}
Solution 2:
useRef() to the rescue.
Since the ref is mutable and exists for the lifetime of the component, we can use it to store the current value whenever it is updated and still access that value in the cleanup function of our useEffect via the ref's value .current property.
So there will be an additional useEffect() to keep the ref's value updated whenever the state changes.
Sample snippet
const [value, setValue] = useState();
const valueRef = useRef();
useEffect(() => {
valueRef.current = value;
}, [value]);
useEffect(() => {
returnfunctioncleanup() {
console.log(valueRef.current);
};
}, []);
Thanks to the author of https://www.timveletta.com/blog/2020-07-14-accessing-react-state-in-your-component-cleanup-with-hooks/. Please refer this link for deep diving.
Solution 3:
I wanted to chime in with an answer for this in case someone else runs into this. If you need more than one value in your useEffect unmount function, it's important to make sure that the correct dependencies are being used. So the accepted answer works fine because it's just one dependency, but start including more dependencies, and it gets complicated. The amount of useRef's you need get out of hand. So instead, what you can do is a useRef that is the unmount function itself, and call that when you unmount the component:
importReact, { useRef, useState, useContext, useCallback, useEffect } from'react';
import { Heading, Input } from'../components';
import { AppContext } from'../../AppContext';
exportconstTitleSection: React.FC = ({ thing }) => {
const { updateThing } = useContext(AppContext);
const [name, setName] = useState(thing.name);
const timer = useRef(null);
const onUnmount = useRef();
const handleChangeName = useCallback((event) => {
setName(event.target.value);
timer.current !== null && clearTimeout(timer.current);
timer.current = setTimeout(() => {
updateThing({
name: name || ''
});
timer.current = null;
}, 1000);
}, [name, updateThing]);
useEffect(() => {
onUnmount.current = () => {
if (thing?.name !== name) {
timer.current !== null && clearTimeout(timer.current);
updateThing({
name: name || '',
});
timer.current = null;
}
};
}, [thing?.name, name, updateThing]);
useEffect(() => {
return() => {
onUnmount.current?.();
};
}, []);
return (
<><Headingas="h1"fontSize="md"style={{marginBottom:5 }}>
Name
</Heading><Inputplaceholder='Grab eggs from the store...'value={name}onChange={handleChangeName}variant='white'
/></>
);
};
Post a Comment for "How To Access State When Component Unmount With React Hooks?"