1

React ネイティブ アプリを開発し、React ルーター ネイティブ v4 を使用しています。ドキュメントで示唆されているように、アニメーション部分を開発しようとしています。最初に、すべてがアニメーションやトランジションなしで機能することを確認しました。

私は実装を繰り返しましたが、これは私が今得た限りです:

私のメインコンポーネントは以下をレンダリングします:

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

私の routes.js は次をレンダリングします (親コンポーネントの前に子を更新しないように、Switch に渡された location プロパティに注意してください):

// 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>
    );
  }
}

上記のコードは機能しており、古いビューがフェードアウトし、新しいビューがフェードインするのを見ることができますが、問題があります.フェードアウトし始めると、どういうわけかコンポーネントが再びマウントされ、アニメーションが始まる直前にまばたきが見られます.私のコードの何が問題なのかを知るために。

4

3 に答える 3

1

上記のコードを修正することができました.reactコンポーネントのライフサイクルでcomponentWillUpdateメソッドがすでにnextPropsを子に渡していることが起こりました.その間、私のコンポーネントは古い子で新しい状態を設定し、Switchはレンダリングを準備しています. oldChildren のアンマウントと新しい子のマウントを生成する新しいものの中で、最終的に私のコンポーネントが状態の設定を終了すると、古い子は既にアンマウントされており、再度マウントする必要があります。

componentWillUpdate上記の話は「アニメーションが始まると瞬きが見える」という長い話ですが、解決策はたまたま簡単でしcomponentWillReceivePropsた。現在の子をキャッチし、状態に割り当て、スイッチがマウントを解除する前にレンダリングし、フェードアウトのためにビューに保持するのに十分な時間を与えてくれるので、もう点滅しません。

私の最終的なview-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>
    );
  }
}
于 2018-03-02T22:06:59.823 に答える
-1

うーん..少し遅すぎることはわかっています。react -router-native-animate-stackを試すことができるかもしれません

のサブコンポーネントですreact-router-native。ただし、アニメーション化可能で、スタック機能を提供します。switchコンポーネントに触発されており、知っていればswitch、このパッケージの使い方がわかります。

デフォルトの動作

カスタマイズ

于 2020-03-26T03:15:24.817 に答える