Traviskn / react-router-native-stack

A stack navigation component for react-router-native
MIT License
171 stars 36 forks source link

Warning: componentWillReceiveProps has been renamed and is not recommended for use. #52

Open JoeToeniskoetter opened 4 years ago

JoeToeniskoetter commented 4 years ago

componentWillReceiveProps method on the StackTransitioner component should be replaced with static getDerivedStateFromProps().

Taymindis commented 4 years ago

getDerivedStateFromProps() or memoize() ?

Taymindis commented 4 years ago

I have created with animation stack with getDerivedStateFromProps flow

react-router-native-animate-stack

Dinkelborg commented 4 years ago

Seeing that this was opened last December and the issue still persist today I assume this project is dead?

Taymindis project unfortunately has its own flaws and also doesn't work

Dinkelborg commented 4 years ago

So I took a look at where componentWillReceiveProps is actually used and checked what else react had in stock

I am fairly unexperienced in react so please correct me if the following is wrong but I replaced componentWillReceiveProps with shouldComponentUpdate in StackTransitioner.js and it seems to work fine

shouldComponentUpdate(nextProps,nextState) {
    const { history } = nextProps;
    const { location } = this.props;
    let _shouldUpdate = true;
    if(this.props === nextProps && this.state === nextState) _shouldUpdate = false;

    if (nextProps.location.key === location.key || !!this.state.transition) {
      return _shouldUpdate;
    }

    let action = history.action

    if (action === REPLACE && this.props.replaceTransitionType) {
        action = this.props.replaceTransitionType
    }

    const [children, previousChildren] = this.getChildren(nextProps.location, location);
    const routeAnimationType =
      action === PUSH ? (children && children.props.animationType) : (previousChildren &&  previousChildren.props.animationType)

    this.setState({
      previousLocation: location,
      routeAnimationType,
      children,
      previousChildren,
    });

    if (
      this.isPanning ||
      (routeAnimationType === NONE || (nextProps.animationType === NONE && !routeAnimationType)) ||
      (action === POP && history.index < this.startingIndex) ||
      (children && previousChildren && children.key === previousChildren.key)
    ) {
      return _shouldUpdate;
    }

    if (action === PUSH || action === POP) {
      this.setState(
        {
          transition: action,
        },
        () => {
          // TODO: base slide direction on `I18nManager.isRTL`
          const dimension = this.getDimension();

          this.props.isAnimating(true);

          this.animation = Animated.timing(this.animatedValue, {
            duration: getDuration(routeAnimationType || nextProps.animationType, action),
            toValue: action === PUSH ? -dimension : dimension,
            easing: getEasing(routeAnimationType || nextProps.animationType),
            useNativeDriver: true,
          }).start(({ finished }) => {
            if (finished) {
              this.props.isAnimating(false);

              this.setState({
                previousLocation: {},
                transition: null,
              });

              if (action === POP) {
                this.setState({
                  routeAnimationType: children.props.animationType,
                });
              }

              this.animatedValue = new Animated.Value(0);
              this.animation = null;
            }
          });
        }
      );
    }
    return _shouldUpdate;
  }

So maybe this could be adapted and thus fix the only issue I have with this plugin?