Static getDerivedStateFromProps, which requires previous details and a state callback?

I just updated to respond to native 0.54.0, which also includes alpha 1 of reaction 16.3, naturally, I get a lot of warnings about the wear of componentWillMount and componentWillReceiveProps .

I have an animated route component that relied on componentWillReceiveProps , in essence it gets a new path, compares it with the previous one, if it puts old children, animates them, sets new children and animates them.

Here is the code in question:

 componentWillReceiveProps(nextProps: Props) { if (nextProps.pathname !== this.props.pathname) { this.setState({ previousChildren: this.props.children, pointerEvents: false }, () => this.animate(0) ); } } 

Now for questions regarding the transfer of this value to static getDerivedStateFromProps

1) I no longer have access to this.props , therefore there is no access to the previous path, I think I can keep these details in a state, is this the right approach now? This is like repeating data.

2) Since I do not have access to this , I cannot name my animation function that relies on state. How can I get around this?

3) I need to set the state first and then call the animation, since getDerivedStateFromProps sets the state by returning values, after that I can not do much, so is there a way to set the state and then execute the Callback?

4) the pathname bit is only used in componentWillReceiveProps right now if I put it into a state and never use this.state inside getDerivedStateFromProps (because I cannot) this.state.pathname errors are as defined, but have never been used. Is the best approach here to make it static?

My first instinct was to change it to componentDidUpdate , but we should not use setState inside it correctly? (this works in my scenario, though).

  componentDidUpdate(prevProps: Props) { if (this.props.pathname !== prevProps.pathname) { this.setState({ previousChildren: prevProps.children, pointerEvents: false }, () => this.animate(0) ); } } 

NOTE. . As far as I heard, I think there is a function that appears in the β€œpause” that will allow us to save views set to the unmount event of the component? I was unable to find a link to this, but it looks like what I could use for this animation

For everyone who is interested, this is a snippet for the full component in question

 // @flow import React, { Component, type Node } from "react"; import { Animated } from "react-native"; type Props = { pathname: string, children: Node }; type State = { animation: Animated.Value, previousChildren: Node, pointerEvents: boolean }; class OnboardingRouteAnomation extends Component<Props, State> { state = { animation: new Animated.Value(1), previousChildren: null, pointerEvents: true }; componentWillReceiveProps(nextProps: Props) { if (nextProps.pathname !== this.props.pathname) { this.setState({ previousChildren: this.props.children, pointerEvents: false }, () => this.animate(0) ); } } animate = (value: 0 | 1) => { Animated.timing(this.state.animation, { toValue: value, duration: 150 }).start(() => this.animationLogic(value)); }; animationLogic = (value: 0 | 1) => { if (value === 0) { this.setState({ previousChildren: null, pointerEvents: true }, () => this.animate(1)); } }; render() { const { animation, previousChildren, pointerEvents } = this.state; const { children } = this.props; return ( <Animated.View pointerEvents={pointerEvents ? "auto" : "none"} style={{ alignItems: "center", opacity: animation.interpolate({ inputRange: [0, 1], outputRange: [0, 1] }), transform: [ { scale: animation.interpolate({ inputRange: [0, 1], outputRange: [0.94, 1] }) } ] }} > {previousChildren || children} </Animated.View> ); } } export default OnboardingRouteAnomation; 
+5
source share
1 answer

For reaction version 16.3, you can still use componentWillReceiveProps , but just show the warning as deprecated. He will delete for version 17 as his tweet . But watch out for production like his tweet .

Let's look at your questions:

1) I no longer have access to this.props, therefore, I don’t have access to the previous path, I think I can keep these details in a state, is this the right approach now? This is like repeating data.

Yes.

If you want to update the component (re-rendering), you should combine props and state . In your case, you want to update the component (trigger animation) when the pathname has changed, so you need the life cycle of the game component.

It looks like data repetition.

it looks like you need to read this: Documentation

2) Since I do not have access to this, I can not name my animation function, which relies on state. How can I get around this?

You can bypass in componentDidUpdate . Lets get a quote from this blog :

componentDidUpdate

This function will be called after rendering is completed in each re-render cycle. This means that you can be sure that the component and all its subcomponents are correctly displayed by themselves.

As you can see, you can call the animation after setState in componentDidUpdate

3) I need to set the state first and then call the animation, since getDerivedStateFromProps sets the state by returning values, after that I can not do much, so is there a way to set the state and then call back?

I think this applies to no 2

4) the pathname bit is only used in the WillreceiveProps component right now if I put it into a state and never use this.state inside getDerivedStateFromProps (because I cannot) this.state.pathname errors are as specific, but never used. Is the best approach here to make it static?

No, it will be used by the DidUpdate component

allows you to go to the code in which the sample of your example is located:

 // @flow import React, { Component, type Node } from "react"; type Props = { pathname: string, children: Node }; type State = { previousChildren: Node, pointerEvents: boolean }; class OnboardingRouteAnomation extends Component<Props, State> { state = { previousChildren: null, pointerEvents: true, pathname: '' }; static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.pathname !== prevState.pathname) { return { previousChildren: nextProps.children, pointerEvents: false, pathname: nextProps.pathname }; } return null; } componentDidUpdate(prevProps, prevState) { if (prevState.pathname !== this.state.pathname){ console.log("prevState.pathname", prevState.pathname); console.log("this.props.pathname", this.props.pathname); this.animate(0); } } componentDidMount(){ this.setState({ pathname: this.props.pathname}); } animate = (value: 0 | 1) => { console.log("this animate called", this); animationLogic(value); }; animationLogic = (value: 0 | 1) => { if (value === 0) { this.setState({ previousChildren: null, pointerEvents: true }, () => this.animate(1)); } }; render() { const { animation, previousChildren, pointerEvents } = this.state; const { children } = this.props; return ( <div> {this.props.children} </div> ); } } export default OnboardingRouteAnomation; 

which for my example is removed in the case of componentWillReceiveProps . I think it responds to thinking. Animation of a component after an update in componentDidUpdate (side effect).

You can better approach with the state of names, for example isPathUpdated with boolean, then function animate check isPathUpdated , and then play the game.

+4
source

Source: https://habr.com/ru/post/1275763/


All Articles