web-dev-qa-db-ja.com

goBack()で前の画面を更新

私はReact Nativeです。元の画面に戻るときに、goBack()を呼び出して前の画面を更新/再読み込みするにはどうすればよいですか?]

3つの画面A、B、Cがあるとします。

_A -> B -> C
_

画面CからgoBack()を実行すると、画面Bに戻りますが、古い状態/データが使用されます。どのように更新できますか?コンストラクターは2回呼び出されません。

15
Adnan Ali

はい、コンストラクタは初めて呼び出されるだけで、2回呼び出すことはできません。

最初:ただし、データゲッター/セッターをコンストラクターから分離して関数に入れると、次のシーンに関数を渡すことができ、戻るときはいつでも単純に関数を呼び出します。

より良い:最初のシーンで戻る関数を作成し、戻るときにシーンを更新し、戻る関数を渡すことができます。この方法では、2番目のシーンは更新機能を認識せず、合理的です。

Best:reduxを使用して、2番目のシーンでゴーバックアクションをディスパッチできます。次に、リデューサーでシーンに戻ってリフレッシュします。

2
Bat

Api Callをコールバックに追加すると、問題が解決します

componentDidMount() {
    this.props.fetchData();
    this.willFocusSubscription = this.props.navigation.addListener(
      'willFocus',
      () => {
        this.props.fetchData();
      }
    );
  }

  componentWillUnmount() {
    this.willFocusSubscription.remove();
  }
26
Mukundhan

React-Navigationに付属する組み込みのリスナー関数が最も簡単なソリューションです。戻って戻ることによってコンポーネントが再び「フォーカス」されると、リスナーは起動します。コンポーネントのロード時とリスナーへの通知時の両方で呼び出すことができるloadData関数を記述することにより、戻るときに簡単にデータをリロードできます。

   componentWillMount(){
    this._subscribe = this.props.navigation.addListener('didFocus', () => {
     this.LoadData();
     //Put your Data loading function here instead of my this.LoadData()
    });}
5
RawBData

画面上では、コンストラクターは魔法のように機能します:)

    this.props.navigation.addListener(
          'didFocus',
          payload => {
            this.setState({is_updated:true});
          }
    );
4
Brijesh Singh

悲しいことに、これらの答えはどれもうまくいきませんでしたが、簡単なライブラリを見つけました。

npm install --save react-native-event-listeners

componentDidMount() {
        this.listener = EventRegister.addEventListener('reloadData', (data) => {
            console.log("data is fetched");
            this.updateState(data); // private function that update the state using setState to trigger render
        });
    }

componentWillUnmount() {
    EventRegister.removeEventListener(this.listener)
}

そして、他のコンポーネントでは、私の場合は不透明度ボタン:

<TouchableOpacity
            onPress={() => {
                fetch('url').then(data => {
                    ServiceLocator.saveData('matba', data);
                    EventRegister.emit('reloadData', data);
                    props.nav.goBack()
                })
                    .catch(error =>{
                        console.log(error);
                        Alert.alert("Cannot connect to the server");
                        props.nav.goBack()
                    });
            }}
        >

前のビューに新しいデータを取得しようとしていて、それが機能していない場合は、最初にそのビューにデータをパイプする方法を再検討することをお勧めします。 goBackを呼び出しても、以前のコンポーネントのマウントには影響しません。また、既に述べたように、コンストラクターを再度呼び出すことはないでしょう。

最初のステップとして、 ComponentPureComponent 、または Functional Component を使用しているかどうかを尋ねます。コンストラクターのコメントに基づいて、コンポーネントクラスを拡張しているように聞こえます。

コンポーネントを使用している場合、renderメソッドは shouldComponentUpdate の対象となり、状態の値はコントロール内にあります。

componentWillReceiveProps を使用して、コンポーネントが新しいデータを受信して​​いることを検証し、その状態が新しいデータを反映するように更新されていることを確認することをお勧めします。

コンストラクターを使用して何らかのAPIまたは非同期関数を呼び出す場合は、goBackを呼び出しているルートと更新するコンポーネントの両方の親コンポーネントにその関数を移動することを検討してください最新のデータを使用します。その後、親コンポーネントにAPIの再クエリを依頼するか、子コンポーネントから状態を更新します。

ルートCがアプリケーションの「状態/データ」を更新する場合、その更新はルートA、B、およびCの共有された親に伝播され、次に小道具として渡される必要があります。

あるいは、 Redux のような状態管理ソリューションを使用して、その状態を親/子コンポーネントとは無関係に維持できます。コンポーネントをconnect高次コンポーネントでラップして、最新のアプリケーションの状態が変更されるたびに更新されます。

TL; DR最終的には、質問に対する答えは、アプリケーションの状態が保存されている場所に根ざしているように聞こえます。各階層が常に親から渡された最新のデータを小道具として受け取ることができるように、コンポーネント階層の十分に高い場所に保存する必要があります。

0
joel.bowen

この答えは、react-native-navigationライブラリが使用されていることを前提としていますが、実際にはgoBack()メソッドがないためです...

画面AとBはまだレンダリングされている(ただし画面Cの後ろに隠れている)ため、コンストラクターは2回呼び出しません。画面Bが再び表示されるタイミングを知る必要がある場合は、 ナビゲーションイベント を聞くことができます。

class ScreenB extends Component {
  constructor(props) {
    super(props);
    // Listen to all events for screen B
    this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
  }

  onNavigatorEvent = event => {
    switch (event.id) {
      case 'willAppear':
        // refresh your state...
        break;
  };
}

その他のイベント:willDisappeardidAppeardidDisappear

問題の別の解決策は、Reduxなどの状態管理ソリューションを使用して、画面の遷移時ではなく、更新されるたびにすべての画面に状態を提供することです( old react-native-navを参照)/reduxの例

0
Royce Townsend