我刚刚更新了react native 0.54.0,其中还包括react 16.3的alpha 1,当然我会收到很多关于componentWillMountcomponentWillReceiveProps贬值的警告.

我有一个动画路由组件,它的核心依赖于componentWillReceiveProps,它接收新路径,将其与前一个进行比较,如果它们是设置旧的子对象,则设置它们的动画,设置新的子对象并设置它们的动画.

下面是有问题的代码:

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

现在我想问一下关于将其移植到static getDerivedStateFromProps的问题

1) 我不再有访问this.props的权限,因此无法访问以前的路径名,我想我可以将这些props 存储在状态中,现在这种方法正确吗?似乎是重复数据.

2) 由于我无法访问this,我无法调用动画函数,这取决于状态.我怎么能绕过这个?

3) 我需要先设置状态,然后调用动画,因为通过返回值来设置getDerivedStateFromProps个状态,之后我不能做很多事情,所以有没有办法设置状态,然后执行回调?

4) pathname位现在只在componentWillreceiveProps中使用,如果我将其移动到状态,并且在getDerivedStateFromProps中从不使用this.state(因为我不能)定义的this.state.pathname个错误,但从未使用.这里最好的方法是让它也是静态的吗?

我的第一react 是把它改成componentDidUpdate,但我们不应该在里面用setState,对吗?(但在我的场景中,这确实有效).

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

NOTE:据我所知,我认为《悬念》中有一个功能,可以让我们在组件卸载事件中保持视图的安装?我找不到这方面的任何参考资料,但这听起来像是我可以在这部动画中使用的东西

对于任何感兴趣的人来说,这是一个完整组件的片段

// @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;

推荐答案

对于react版本16.3,使用componentWillReceiveProps是可以的,但会导致控制台中显示弃用警告.It will be removed in version 17.FWIW Dan Abramov has warned against using alpha functionality in production——但这是在2018年3月.

让我们浏览一下你的问题:

1) 我再也不能接触这个了.props ,因此无法访问以前的路径名,我想我可以将这些props 存储在状态中.现在这是正确的方法吗?似乎是重复数据.

Yes.

如果要更新/重新渲染组件,应将propsstate组合起来.在您的情况下,您希望在使用生命周期方法更改pathname时更新组件/触发器动画.

似乎是重复数据.

看看这个:React Team post on State and Lifecycle

2) 因为我无法访问这个函数,所以无法调用我的动画函数,它依赖于状态.我怎么能绕过这个?

Use componentDidUpdate

componentDidUpdate

在每个重新渲染周期中完成渲染后,将调用此函数.这意味着您可以确保组件及其所有子组件已正确渲染自身.

这意味着你可以在componentDidUpdatesetState之后拨打animate

3) 我需要先设置状态,然后调用动画,因为getDerivedStateFromProps通过返回值来设置状态,之后我不能做很多事情,所以有没有办法设置状态,然后执行回调?

参考第2点(Use componentDidUpdate)

4) 路径名位现在只在componentWillreceiveProps中使用,如果我将其移动到state并且从不使用它.在getDerivedStateFromProps中声明(因为我不能)这个.状态已定义但从未使用的路径名错误.这里最好的方法是让它也是静态的吗?

No, It will used by componentDidUpdate

以下是我的做法:

// @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;

我相信这就是react开发者想要处理的方式.你应该

我会使用更具描述性的名称来表示路径已更改.大约isPathUpdated.然后你可以用animate判断isPathUpdated作为切换.

React-native相关问答推荐

在AWS-Amplify js v6中检索原始的accesToken和idToken

嵌套的FlatList内的Incorrect Padding

单击react 本机时如何从同一屏幕更改内容

RTK 查询显示互联网何时关闭?

react native :navigationOptions 中的标题样式不起作用

在 React Native 中从 Modal 打开 Modal

ReactJS 应用多种内联样式

React Native WebView onMessage 没有做任何事情

如何在 React Native 的嵌套 Touchable 中传播touch 事件?

什么时候适合在 React 中使用构造函数?

在整个屏幕上获取touch 事件

如何在 React Native 中使用断点进行调试

React-Native iOS - 如何通过按下按钮从 React-Native 视图导航到非 React-Native 视图(本机 iOS 视图控制器)?

Android 构建错误AndroidManifest.xml requires a placeholder substitution

react-native run-ios 运行失败: Application is unknown to FrontBoard?

React Native - React Navigation导航转换

React Native Image 不显示,我该如何解决?

如何知道 FlatList 中的滚动状态?

Tools > Android 菜单在 Android Studio 中不存在

I18nManager.forceRTL 不会在首次应用加载时应用更改