Hi!
Help me understand how to do refactoring:
deprecated componentWillMount is recommended to replace with componentDidMount (this method is not called on the server-side) or with static getDerivedStateFromProps which has no access to a particular instance.
so where to put the code which must be running on both sides after initialization of an instance?
@budarin There is mention in Note
in blog post
https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#fetching-external-data
When supporting server rendering, it’s currently necessary to provide the data synchronously – componentWillMount was often used for this purpose but the constructor can be used as a replacement. The upcoming suspense APIs will make async data fetching cleanly possible for both client and server rendering.
@TrySound
I'm sorry - I don't need to fetch data )
Imagine component like a Loadable: after initialization it has to check for loading component and initialize its loading on both sides: browser and server.
Constructor is not suitable place for this - there is no access for the components instance.
And componentDidMount is not called on server side
But constructor has an access to instance. What do you mean?
Constructor is not suitable place for this - there is no access for the components instance.
@TrySound
thanks for pointing )
I'm sorry - I was mistaken !
I have a bug in my code...
@TrySound Given this change, should the docs be updated for the React API here where it essentially says not to have any side-effects in the constructor? Anything for developers to watch out for?
cc: @bvaughn
Setting the initial state is not a side effect.
@gaearon To clarify, I was suggesting clarifying the answer to the following question: _What lifecycle method should one use on the server to fetch data (say from Redux action or XHR), given that componentWillMount
is going away and componentDidMount
doesn't execute on the server?
We're still working on a good story for server-side data fetching (dubbed "suspense").
componentWillMount
is going away, but UNSAFE_ componentWillMount
is still here (and won't be going anywhere). There's also the constructor, which is the same (equally bad) as componentWillMount
was.
What lifecycle method should one use on the server to fetch data (say from Redux action or XHR), given that componentWillMount is going away and componentDidMount doesn't execute on the server?
To be extra clear componentWillMount
was never very helpful on the server for data fetching since it executes synchronously.
So you had to render in two passes (once to start the fetch and then another time after it’s resolved). It’s not an optimal architecture but while you depend on it you can keep using UNSAFE_componentWillMount
for the same purpose. (Or constructor, I guess.)
When “suspense” API is ready, it will be the preferred solution because it will let you wait for data both on the client and on the server. Without rendering twice.
@gaearon
I have a problem with new lifecycle
I have a HOC to add/remove styleSheets from components module using CSSModules in useable mode:
function withStyles(styles) {
return function(BaseComponent) {
class componentWithStyles extends React.Component {
count: number = 0;
componentWillMount() {
// We need a counter because with Fiber cWM may be called multiple times
this.count += 1;
if (this.count === 1) {
styles.use();
}
}
componentWillUnmount() {
styles.unuse();
}
render() {
return <BaseComponent {...this.props} css={styles} />;
}
}
return componentWithStyles;
};
}
when I move code from componentWillMount to constructor I'v got a strange bug: styles doesn't work correctly as before.
I have different styles for a page layout component for different routes. When I move code to a new lifecycle - styles are not removed when I return from a route to previous
function withStyles(styles) {
return function(BaseComponent) {
class componentWithStyles extends React.Component {
count: number = 0;
constructor(props) {
super(props);
// We need a counter because with Fiber cWM may be called multiple times
this.count += 1;
if (this.count === 1) {
styles.use();
}
}
componentWillUnmount() {
styles.unuse();
}
render() {
return <BaseComponent {...this.props} css={styles} />;
}
}
return componentWithStyles;
};
}
Don’t keep a counter like this. That’s not the intended migration strategy. If it’s nowhere in our blog post it’s probably not the recommended way. 🙂
You should move code with side effects (like your example) into componentDidMount
. If you have further problems please share a reproducing case.
What do styles.use()
and styles.unuse()
do? Can you call styles.use()
from componentDidMount
/ componentDidUpdate
instead?
What happens if you call styles.use()
more times than styles.unuse()
? Because as long as you're doing this from the a lifecycle like the constructor or componentWillMount
- this is possible.
@bvaughn
styles.use() - add styles into head
Most helpful comment
Setting the initial state is not a side effect.