この画面に遷移すると、最新のデータを取得するためのAPI呼び出しが行われます。しかし、それがクラスバージョンでうまく機能しているときに、フックバージョンのある別のナビゲーションスタックから遷移するときに、didFocusイベントがトリガーされてAPI呼び出しがトリガーされないようです。
フックバージョンをクラスバージョンと同じ動作にするにはどうすればよいですか?
この2つのバージョンの違いは何ですか?
class someScreen extends Component {
componentDidMount() {
const {
navigation,
} = this.props;
this.navFocusListener = navigation.addListener('didFocus', () => {
// do some API calls here
console.log("class version");
API_CALL();
});
}
componentWillUnmount() {
this.navFocusListener.remove();
}
}
他のナビゲーションスタックからこの画面への遷移:クラスバージョン
同じスタック内の画面間の遷移:クラスバージョン
const someScreen = ({
navigation,
}) => {
useEffect(() => {
const navFocusListener = navigation.addListener('didFocus', () => {
// do some API calls here
API_CALL();
console.log('hooooks');
});
return () => {
navFocusListener.remove();
};
}, []);
}
他のナビゲーションスタックからこの画面への移行:コンソールには何も表示されません
同じスタック内の画面間の遷移:フック
ところで、ここに私が見つけた回避策のソリューションがあります
const someScreen = ({
navigation,
}) => {
useEffect(() => {
const isFocused = navigation.isFocused();
// manually judge if the screen is focused
// if did, fire api call
if (isFocused) {
// do the same API calls here
API_CALL();
console.log('focused section');
}
const navFocusListener = navigation.addListener('didFocus', () => {
// do some API calls here
API_CALL();
console.log('listener section');
});
return () => {
navFocusListener.remove();
};
}, []);
}
コンソール出力
他のナビゲーションスタックからこの画面への移行:フォーカスセクション
同じスタック内の画面間の遷移:リスナーセクション
一貫性のない行動の根本的な原因を見つけたと思います。 useLayoutEffectと呼ばれる別のフックがあります
useLayoutEffectシグネチャはuseEffectと同じですが、すべてのDOM変更の後で同期的に起動します。これを使用して、DOMからレイアウトを読み取り、同期的に再レンダリングします。ブラウザがペイントする機会がある前に、useLayoutEffect内でスケジュールされた更新は同期的にフラッシュされます。
useLayoutEffectは描画をブロックしますが、useEffectはブロックしません。これは、didFocusイベントが発生したが、タイミングを逃したためにリスナーをトリガーしなかったと私の推測を確認して説明します
私の場合は、useEffectの代わりにuseLayoutEffectを使用する必要があります
参照: https://kentcdodds.com/blog/useeffect-vs-uselayouteffecthttps://reactjs.org/docs/hooks-reference.html#uselayouteffect