Imagine you have a simple component Post
which just renders a post page.
export const Post = (): JSX.Element => {
const [value, setValue] = useState<string>()
const url = 'http://somewhere.com/something'
useEffect(() => {
axios.get(url).then<string>((response) => {
setValue(response.data)
})
}, [])
return <div>{value}</div>
}
Just for simplicity purpose let's output just a single string.
And now a question: What will be if we go to another page (or Post
component will be unmounted in some other way) before the data load finish?
In this case we will get this warning in the console:
Nothing is broken. The app still works. App users may not even notice any problems except for the red warning in the console.
You can leave it as is, but you should know that each such event causes a memory leak. At some point, it could become a problem.
The easiest solution is to use the useSafeState
hook from the ahooks package. Just replace your useState
with useSafeState
, and everything will work out of the box.
const [value, setValue] = useSafeState<string>();
I highly recommend to check the source code of useSafeState
and research how it works. The code is not too large, so it's not a big deal.
By the way useSafeState
under the hood uses highly usefull useUnmountedRef
hook, which checks if component is unmounted.
However, that is a topic for another story :)
Top comments (2)
Hmm I'm not sure about this... It seems nice at first but people will use this hook to obscure the fact that they're forgetting to cleanup their side effects... I would not recommend people use this... If it's really a problem and its not fixable by doing correct side effect cleanup, you can implement your own isMounted check pretty easily... Putting that check in a blackbox obscures what is really going on in the side effect. The naming of the hook further encourages people to think that this is a safe way to fix this error, which it isn't... If it had a more verbose name like:
useStateOnlyWhenMounted
, it would be more clear what is going on.In my opinion, moving code parts to reusable functions is a good practice. It helps and doesn't obscure.
But yes, the naming is not the best. It's up to the 'ahooks' developers.
And I agree, may not be a great idea to install additional package just for one tiny hook, which can be easily written from scratch