web-dev-qa-db-ja.com

ナビゲーション後に `componentDidMount()`関数が呼び出されない

画面間の移動にstackNavigatorを使用しています。 2番目のアクティビティのcomponentDidMount()関数で2つのAPIを呼び出しています。初めてロードすると、正常にロードされます。次に、戻るボタンを押して、最初のアクティビティに戻ります。次に、2番目のアクティビティに再び行くと、APIが呼び出されず、レンダリングエラーが発生します。これに対する解決策を見つけることができません。任意の提案をいただければ幸いです。

17
hitttt

2019年にここに来る人がいれば、これを試してください:

import {NavigationEvents} from 'react-navigation';

コンポーネントをレンダーに追加します。

<NavigationEvents onDidFocus={() => console.log('I am triggered')} />

これで、このonDidFocusイベントは、goBack()またはナビゲートから来たにもかかわらずページがフォーカスされるたびにトリガーされます。

37
Jithesh Kt

NavigationEventsコンポーネントを使用する賛成の構文が機能しない場合は、次の方法で試すことができます。

// no need to import anything more

// define a separate function to get triggered on focus
onFocusFunction = () => {
  // do some stuff on every screen focus
}

// add a focus listener onDidMount
async componentDidMount () {
  this.focusListener = this.props.navigation.addListener('didFocus', () => {
    this.onFocusFunction()
  })
}

// and don't forget to remove the listener
componentWillUnmount () {
  this.focusListener.remove()
}
8
vitosorriso

React-navigationは、画面間を移動してもコンポーネントをマウントしたままにします。コンポーネントを使用して、これらのイベントに対応できます。

<NavigationEvents
  onDidFocus={() => console.log('hello world')}
/>

このコンポーネントの詳細 ここ

4
SebLambla

React-navigationのドキュメント この場合は明示的に説明

画面AとBを備えたスタックナビゲーターについて考えてみます。 Bをプッシュすると、そのcomponentDidMountも呼び出されますが、Aはスタックにマウントされたままなので、そのcomponentWillUnmountは呼び出されません。

BからAに戻ると、BのcomponentWillUnmountが呼び出されますが、Aはずっとマウントされたままであるため、AのcomponentDidMountは呼び出されません。

現在、そのための3つのソリューションがあります。

ライフサイクルイベントのサブスクライブ

...

React Navigationは、サブスクライブするコンポーネントを選別するイベントを発行します。サブスクライブできる4つの異なるイベントがあります:willFocuswillBlurdidFocusおよびdidBlur。詳細については、APIリファレンスをご覧ください。

ユースケースの多くは、withNavigationFocus高次コンポーネント、_<NavigationEvents />_コンポーネント、またはuseFocusStateフックでカバーできます。

  1. withNavigationFocushigher-order-component
  2. _<NavigationEvents />_コンポーネント
  3. seFocusStateフックdeprecated

withNavigationFocushigher-order-component

_import React from 'react';
import { Text } from 'react-native';
import { withNavigationFocus } from 'react-navigation';

class FocusStateLabel extends React.Component {
  render() {
    return <Text>{this.props.isFocused ? 'Focused' : 'Not focused'}</Text>;
  }
}

// withNavigationFocus returns a component that wraps FocusStateLabel and passes
// in the navigation prop
export default withNavigationFocus(FocusStateLabel);
_

_<NavigationEvents />_コンポーネント

_import React from 'react';
import { View } from 'react-native';
import { NavigationEvents } from 'react-navigation';

const MyScreen = () => (
  <View>
    <NavigationEvents
      onWillFocus={payload => console.log('will focus', payload)}
      onDidFocus={payload => console.log('did focus', payload)}
      onWillBlur={payload => console.log('will blur', payload)}
      onDidBlur={payload => console.log('did blur', payload)}
    />
    {/*
      Your view code
    */}
  </View>
);

export default MyScreen;
_

useFocusStateフック

最初にライブラリをインストール_yarn add react-navigation-hooks_

_import { useNavigation, useNavigationParam, ... } from 'react-navigation-hooks'

function MyScreen() {   const focusState = useFocusState();   return <Text>{focusState.isFocused ? 'Focused' : 'Not Focused'}</Text>; }
_

これが私の個人的な解決策です。onDidFocus()onWillFocus()を使用して、APIからデータがフェッチされたときにのみレンダリングします。

_import React, { PureComponent } from "react";
import { View } from "react-native";
import { NavigationEvents } from "react-navigation";

class MyScreen extends PureComponent {
  state = {
    loading: true
  };

  componentDidMount() {
    this._doApiCall();
  }

  _doApiCall = () => {
    myApiCall().then(() => {
      /* Do whatever you need */
    }).finally(() => this.setState({loading: false}));
  };

  render() {
    return (
      <View>
        <NavigationEvents 
              onDidFocus={this._doApiCall} 
              onWillFocus={() => this.setState({loading: true})}
        />
        {!this.state.loading && /*
        Your view code
        */}
      </View>
    );
  }
}

export default MyScreen;
_
3
Kruupös

Reactでは、componentDidMountは、コンポーネントがマウントされている場合にのみ呼び出されます。親画面で次のようにナビゲートを呼び出すときに、コールバック関数をパラメーターとして渡すことができます。

  navigate("Screen", {
     onNavigateBack: this.handleOnNavigateBack
  }); 
  handleOnNavigateBack = () => {//do something};

そしてチャイルドスクリーン

this.props.navigation.state.params.onNavigateBack();
this.props.navigation.goBack();
0
Suyog K.C

drawernavigatorまたはstacknavigatorを使用してコンポーネントに移動するたびに何かを実行したい。このため、NavigationEventscomponentDidMountよりも適しています。

import {NavigationEvents} from "react-navigation";
<NavigationEvents onDidFocus={()=>alert("Hello, I'm focused!")} />

:ドロワーナビゲーションまたはスタックナビゲーションを使用してコンポーネントにフォーカスした後、NavigationEventsを使用して毎回タスクを実行する場合より良いアイデアです。ただし、タスクを一度実行する場合は、componenetDidMountを使用する必要があります。

0
Taohidul Islam