-
Notifications
You must be signed in to change notification settings - Fork 48.5k
React 16.3 deprecated componentWillMount and SSR? #12495
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@budarin There is mention in
|
@TrySound 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. |
But constructor has an access to instance. What do you mean?
|
@TrySound |
@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 |
We're still working on a good story for server-side data fetching (dubbed "suspense").
|
To be extra clear 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 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. |
I have a problem with new lifecycle 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. 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 |
What do What happens if you call |
styles.use() - add styles into head <style> tag, unuse() - remove particular style tag from head of course I can move code to componentDidMount, but there appears a blinking effect. I suspect that the problem in an unequal numbers use() and unuse() in case of code in constructor |
Hm...this sounds unexpected, if we're talking only about client-side rendered React. Adding the style in If you're talking about server rendering too, then it would make sense- since Sorry if I'm overlooking something silly. I don't have much experience with server rendering. |
Please share a reproducing example. |
@gaearon the problem remains with the server rendering |
@budarin Can you clarify why using |
@bvaughn |
What exactly do you need to do on the server? You can’t attach a stylesheet there because there is no DOM. Can you provide a complete example we can discuss? |
@gaearon I don't know what I need in this situation - I only pointed you to an existing problem and ask you to help me to resolve it ) |
So I think for now the best solution would be to call it in Longer term we may provide a separate server-only hook that you can replace constructor with: reactjs/rfcs#8 |
thanks, that solved my problem. |
May I ask you in this thread to not create another one for a new lifecycle? Where to move code from componentWillReceiveProps when I need to access to the instance and call a method for computing next state or form state which is based on instance props? For an example: componentWillReceiveProps(nextProps, nextContext) {
const { computedMatch, location, path, strict, exact, sensitive } = nextProps;
this.setState(() => ({
match: Route.computeMatch(
{ computedMatch, location, path, strict, exact, sensitive },
nextContext,
),
}));
} move code to a new method moving code to componentDidUpdate(prevProps, prevState, snapshot) {
const { computedMatch, location, path, strict, exact, sensitive } = this.props;
this.setState(() => ({
match: Route.computeMatch(
{ computedMatch, location, path, strict, exact, sensitive },
this.context,
),
}));
} |
You can fix the infinite loop by comparing Alternatively you can move the context reading code into a component above this one, and pass context as a prop to it. Then you would be able to access it in the static lifecycle. |
@gaearon |
@gaearon It should be mentioned in transition guide. in our project there are a lot of places where in |
Again, it’s hard to discuss without specific examples. The primary transition path when you need to change state in response to new props is to use |
Thanks for the explanation |
To clarify, this is incorrect. As the release blog post states explicitly, |
Can I ask how the following example would work with functional/hooks. class MyComponent extends Component {
constructor() {
this.field_id = idGenFn();
}
render() {
return <>
<label for={this.field_id}>Label</label>
<input id={this.field_id} />
</>;
}
} I need a way to run the function once for each instance of a component, but only before the first render. It's kinda near the boundary between a pure function and a function with side effects. I need the ID before I render, or else I will have to render the component twice. If it were more of a side effect (e.g. it takes time), it would make sense to render a loading state and then re-render, but since this side-effect is resolved instantly and predictably (the ids should be the same between runs (question: is this true?)), it seems silly to re-render. EDIT I guess the functional programmer would say " |
@derekdreery Like this const useIdGenFn = () => {
const idRef = React.useRef(null)
if (idRef.current == null) {
idRef.current = idGenFn()
}
return idRef.current
} |
Aah a custom hook! Thankyou! |
I wonder if react-16, when rendering on the server side, will the client also execute the componentDidMount method? |
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?
The text was updated successfully, but these errors were encountered: