Jun Q
Jun Q

Reputation: 443

React async componentWillUnmount

Since React 16, the ordering of componentWillMount and componentWillUnmount is no longer guaranteed due to support for async componentWillUnmount.

In our project that uses React + Redux, however, from page A navigates to page B, for example, page A calls componentWillUnmount to clean up the application state then jump to page B, which calls componentWillMount to fetch data and update the state. Since the ordering of them can not be controlled, sometimes the state get messed up.

What would be the best solution for this issue ?

Upvotes: 4

Views: 6902

Answers (3)

Nik
Nik

Reputation: 2272

There are several ways to solve such issue. But almost all of them are bad practice (e.g. using HOC with return null in first render and then clear up and do async queries, etc.) I don't recommend such ways.

So I recommend spend a little more time to refactor your architecture and separate the state in Redux. I found a good Dan Abramov's post about this issue: https://github.com/facebook/react/issues/11106#issuecomment-344573660

The easiest way to do so is to not reuse the same part of the tree in such a way. Think about it: components are generally expected to be independent. What happens if you render two such "exclusive" components at the same time? They will conflict. This doesn't seem like the right component thinking.

I understand it is more code to avoid such patterns, but in my experence replacing a single state tree branch with an object or an array was enough. For example you can key it by ID (even a dynamically generated one), and then instead of tearing down the old one in time for the new component mounting, you can just point the new component to the branch with new ID, while keeping the old one alive. Then eventually you can emit an action that cleans up unused state branches and only leaves the one with the most recent ID.

Upvotes: 1

JustGage
JustGage

Reputation: 1662

If possible I would separate the state in Redux so the state isn't shared between pages: https://github.com/reactjs/redux/blob/master/docs/api/combineReducers.md

If that's not possible you could try adding your logic into the functions that navigate.

Some more detail to your question might help me to debug such as what you use for routing and what the state is.

for more information on migrating to the new lifecycle methods look here: https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#migrating-from-legacy-lifecycles

Upvotes: 1

Jimi Pajala
Jimi Pajala

Reputation: 2368

You should avoid using componentWillMount life-cycle method and migrate to using newly introduced ones

One of the biggest lessons we’ve learned is that some of our legacy component lifecycles tend to encourage unsafe coding practices. They are:

componentWillMount componentWillReceiveProps componentWillUpdate These lifecycle methods have often been misunderstood and subtly misused; furthermore, we anticipate that their potential misuse may be more problematic with async rendering. Because of this, we will be adding an “UNSAFE_” prefix to these lifecycles in an upcoming release. (Here, “unsafe” refers not to security but instead conveys that code using these lifecycles will be more likely to have bugs in future versions of React, especially once async rendering is enabled.)

You should do data fetching in componentDidUpdate life-cycle method and I prefer doing catching props in getDerivedStateFromProps(nextProps, prevState) method.

I explained this a little In this stackoverflow post and there is a example of using this method.

Upvotes: -1

Related Questions