New LifeCycle in React v16.3
opened this issue · comments
Does static getDerivedStateFromProps(nextProps, prevState)
work?
what you mean?
How can/will we use getDerivedStateFromProps
in recompose?
I'm doing it here using setStatic #648 , it is working like the old componentWillReceiveProps lifecycle, but get warning in console.
FYI, I am initializing state in my withReducer, reducer
is imported from a separate reducer.js file and declared on the top, so I didn't pass a initialState as the 4th argument for withReducer HOC.
I wrote that lifecycle is somehow a recompose mistake, you don't need it at all as it's easier to write ordinary class.
Just write your HOC if you need it, it's very simple
const MyLifecycle = Component => class Bla extends React.Component {
...any lifecycles you like
render() {
return <Component {...this.props} {...this.state} myHandler={this.handler} etc... />
}
}
I see what you meant about setStatic, and thank you very much for the example.
Using a getDerivedStateFromProps
HOC with recompose like this:
derivedStateFromProps HOC:
const derivedStateFromProps = (initialState, updateStateValue) => BaseComponent => {
class DerivedStateFromProps extends React.Component {
state = typeof initialState === 'string' ? this.props[initialState] : initialState;
static getDerivedStateFromProps = updateStateValue;
render() {
return <BaseComponent {...this.props} {...this.state} />;
};
}
return DerivedStateFromProps;
}
Usage:
const enhance = compose(
withReducer('ComponentState', 'dispatch', reducer),
withHandlers(handlers),
derivedStateFromProps('ComponentState', (nextProps, prevState) => {
if (nextProps !== prevState) return { ...etc };
return null;
}),
lifecycle({
componentDidMount() {
...etc.
}
})
);
export default enhance(SomeComponent);
No more Did not properly initialize state during construction. ...etc
warnings too. 😄
@istarkov do you think recompose should have a getDerivedStateFromProps HOC since it's now a static instead of using the deprecating componentWillReceiveProps in the lifecycle HOC? Thanks.
I think to deprecate lifecycle and suggest solution above instead, as what the need to reproduce react api
That make sense... then can probably deprecate setStatic too.
I don't think a derivedStateFromProps
HOC will work.
The problem is recompose effectively gets rid of state, as each line in compose results in a nested component, and the state gets passed into the child component as a prop.
The only solution I can think of is to add an extra optional function parameter to the withState
HOC.
withState(
...
derivedStateFromProps: (nextProps, preState) => newState
)
This also gets rid of the need to do lifecycling in many cases.
Yes, state get pass through as props, so that's the first initialState argument which takes the state name in props as a string, or you can pass your own state in as an object.
In my case above, I use withReducer + withHandlers to dispatch state changes, similar to a local mini redux. I can pass the name of the state into the derivedStateFromProps HOC and it will watch and compare that state and return whatever new state.
If they are deprecating lifecycle and preferring class components, you can come up with what works for you best.
@istarkov you wrote
that lifecycle is somehow a recompose mistake, you don't need it at all as it's easier to write ordinary class.
But doesn't this apply to the most HOCs of recompose? I am using recompose to write more readable and less code.
I mean something like
compose(
connect(null, mapDispatchToProps),
lifecycle({
componentDidMount() {
this.props.loadUser();
},
}),
)(Login);
As I understand your point you want to write an extra HOC for every case? Something like
const triggerLoadUserOnMount = Component => (
class TriggerLoadUserOnMount extends React.Component {
componentDidMount() {
this.props.loadUser();
}
render() {
return <Component {...this.props} />
}
}
);
compose(
connect(null, mapDispatchToProps),
triggerLoadUserOnMount,
)(Login);