动画启动前,React路由器原生动画会闪烁

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动画启动前,React路由器原生动画会闪烁相关的知识,希望对你有一定的参考价值。

我正在开发一个反应本机应用程序并使用React路由器本机v4,我正在尝试开发动画部分,如文档所示,首先我确保一切都没有动画或过渡。

我已经迭代了实现,这就像我现在所做的那样:

我的主要组件呈现以下内容:

// app.js:render
<ConnectedRouter history={history}>
  <App />
</ConnectedRouter>

我的routes.js呈现以下内容(注意传递给Switch的位置道具以防止它在父组件之前更新其子节点):

// routes.js render
<ViewTransition pathname={location.pathname}>
  <Switch location={location}>
    <Route exact path={uri.views.main} component={Dashboard} />
    <Route path={uri.views.login} component={Login} />
    <Route path={uri.views.register} component={Register} />
  </Switch>
</ViewTransition>

以及处理动画的ViewTransition,现在它只是淡化/退出旧视图和新视图:

// view-transition.js
@withRouter
export default class ViewTransition extends Component {
  static propTypes = {
    children: PropTypes.node,
    location: PropTypes.object.isRequired,
  };

  state = {
    prevChildren: null,
    opacity: new Animated.Value(1)
  };

  componentWillUpdate(nextProps) {
    if (nextProps.location !== this.props.location) {
      this.setState({ prevChildren: this.props.children }, this.animateFadeIn);
    }
  }

  animateFadeIn = () => {
    Animated.timing(this.state.opacity, {
      toValue: 0,
      duration: 150
    }).start(this.animateFadeOut);
  };

  animateFadeOut = () => {
    this.setState({ prevChildren: null }, () => {
      Animated.timing(this.state.opacity, {
        toValue: 1,
        duration: 400
      }).start();
    });
  };

  render() {
    const { children } = this.props;
    const { prevChildren, opacity } = this.state;
    return (
      <Animated.View
        style={{
          ...StyleSheet.absoluteFillObject,
          opacity,
          position: "absolute"
        }}
      >
        {prevChildren || children}
      </Animated.View>
    );
  }
}

上面的代码工作正常,我可以看到旧视图逐渐消失,新视图渐渐消失,但我有一个问题,当它开始淡出时,不知何故组件再次重​​新安装,我可以在动画开始之前看到一个闪烁,我希望知道我的代码有什么问题。

答案

我可以修复上面的代码,碰巧在react组件生命周期中的方法componentWillUpdate已经将nextProps传递给子节点,同时我的组件用旧子节点设置新状态,Switch正在准备渲染在新的孩子和新孩子的装载中,当最后我的组件完成设置状态时,旧的孩子已经卸下并且必须再次安装。

上面的故事是长篇故事“我可以看到我的动画开始时眨眼”,解决方案恰好很容易,我不再检查componentWillUpdate中的东西,但是在componentWillReceiveProps,因为新的道具将传递给父组件在它的孩子之前,它给了我足够的时间来捕捉当前的孩子,将它们分配到状态,在Switch卸载它们之前渲染并将它们保持在视图中以便淡出,因此不再闪烁。

我的最终观点 - transition.js:

// view-transition.js
export default class ViewTransition extends Component {
  static propTypes = {
    children: PropTypes.node,
    location: PropTypes.object.isRequired,
  };

  state = {
    prevChildren: null,
    opacity: new Animated.Value(1)
  };

  componentWillReceiveProps(nextProps) {
    if (nextProps.location !== this.props.location) {
      this.setState({ prevChildren: this.props.children }, this.animateFadeIn);
    }
  }

  animateFadeIn = () => {
    Animated.timing(this.state.opacity, {
      toValue: 0,
      duration: 150
    }).start(this.animateFadeOut);
  };

  animateFadeOut = () => {
    this.setState({ prevChildren: null }, () => {
      Animated.timing(this.state.opacity, {
        toValue: 1,
        duration: 400
      }).start();
    });
  };

  render() {
    const { children } = this.props;
    const { prevChildren, opacity } = this.state;
    return (
      <Animated.View
        style={{
          ...StyleSheet.absoluteFillObject,
          opacity,
          position: "absolute"
        }}
      >
        {prevChildren || children}
      </Animated.View>
    );
  }
}

以上是关于动画启动前,React路由器原生动画会闪烁的主要内容,如果未能解决你的问题,请参考以下文章

StackPanel 上的 FluidMoveBehavior 在动画前闪烁

vue项目解决路由跳转页面闪烁问题(过度动画)

React Native(动画和 setState)

加载前启动画面白色闪烁(React Native Expo)

在ViewPager上,在onPageSelected上的片段上启动动画

是啥导致我的动画闪烁