title: static getDerivedStateFromProps that requires previous props and state callback?
body: <p>I have just updated to react native 0.54.0 that also includes alpha 1 of react 16.3, naturally I get a lot of warnings regarding depreciation of <code>componentWillMount</code> and <code>componentWillReceiveProps</code>.</p>
  
  <p>I have an animated route component that was relying on <code>componentWillReceiveProps</code> at its core it receives new path, compares it to previous one, if they are sets old children, animates them out, sets new children and animates them in.</p>
  
  <p>Here is code in question:</p>
  
  <pre><code>componentWillReceiveProps(nextProps: Props) {
      if (nextProps.pathname !== this.props.pathname) {
        this.setState({ previousChildren: this.props.children, pointerEvents: false }, () =&gt;
          this.animate(0)
        );
      }
    }
  </code></pre>
  
  <p>Now for the questions I have regarding porting this to <code>static getDerivedStateFromProps</code></p>
  
  <p>1) I no longer have access to <code>this.props</code>, hence no access to previous pathname, I guess I can store these props in state, is this correct approach now? Seems like repetition of data.</p>
  
  <p>2) As I have no access to <code>this</code> I can't call my animation function, that relies on a state. How can I bypass this?</p>
  
  <p>3) I need to first set state and then call the animation, as <code>getDerivedStateFromProps</code> sets state by returning the values, I can't do much afterwards, so is there a way to set state and after thats done execute a callback?</p>
  
  <p>4) <code>pathname</code> bit is only used in <code>componentWillreceiveProps</code> right now, if I move it to state and never use <code>this.state</code> inside <code>getDerivedStateFromProps</code> (because I can't) <code>this.state.pathname</code> errors as being defined but never used. Is the best approach here to make it static as well?</p>
  
  <p>My first instinct was to change it to <code>componentDidUpdate</code>, but we are not supposed to use <code>setState</code> inside of it correct? (this does work in my scenario though).</p>
  
  <pre><code>  componentDidUpdate(prevProps: Props) {
      if (this.props.pathname !== prevProps.pathname) {
        this.setState({ previousChildren: prevProps.children, pointerEvents: false }, () =&gt;
          this.animate(0)
        );
      }
    }
  </code></pre>
  
  <p><strong>NOTE:</strong> As far as I heard I think there is a feature coming in "suspense" that will allow us to keep views mounted on component unmount event? I wasn't able to find any reference to this, but it sounds like something I could potentially utilise for this animation</p>
  
  <p>For anyone interested, this is snippet for a full component in question</p>
  
  <pre><code>// @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&lt;Props, State&gt; {
    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 }, () =&gt;
          this.animate(0)
        );
      }
    }
  
    animate = (value: 0 | 1) =&gt; {
      Animated.timing(this.state.animation, {
        toValue: value,
        duration: 150
      }).start(() =&gt; this.animationLogic(value));
    };
  
    animationLogic = (value: 0 | 1) =&gt; {
      if (value === 0) {
        this.setState({ previousChildren: null, pointerEvents: true }, () =&gt; this.animate(1));
      }
    };
  
    render() {
      const { animation, previousChildren, pointerEvents } = this.state;
      const { children } = this.props;
      return (
        &lt;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] })
              }
            ]
          }}
        &gt;
          {previousChildren || children}
        &lt;/Animated.View&gt;
      );
    }
  }
  
  export default OnboardingRouteAnomation;
  </code></pre>