こんばんは。今夜もReact Nativeと戦っております。
前置きも省略し、早速本題に参りたいと思います。
Contents
前提
以下の構成ですが、今回のエラーは単純にReact Nativeのエラーのようです。
- React Native
- Expo
- TypeScript
問題
以下のような構成のFunction達の間で、Functionを跨いでStateを更新しようとすると、エラーが発生しました。
<アプリケーションコードの構成>
こんな感じで、FuncAの中でstateを定義しているのですが、これをFuncAの中のFuncBから更新しようとしたら怒られました。
export const FuncA = () => {
const [value, setValue] = useState(0);
#################
const FuncB = () => {
setValue(1)
・・・
return (
・・・
)
}
#################
return (
・・・
);
};
<エラーの内容>
Warning: Cannot update a component from inside the function body of a different component.
at [native code]:null in dispatchAction
at app/app.navigator.tsx:407:21 in MainFlow
at [native code]:null in performSyncWorkOnRoot
at [native code]:null in dispatchAction
at app/app.navigator.tsx:93:37 in profileGetApi.then$argument_0
at [native code]:null in flushedQueue
at [native code]:null in invokeCallbackAndReturnFlushedQueue
原因と解決方法
こちらのQiitaの記事が分かりやすくまとめられていて、大変参考になりました。
https://qiita.com/FumioNonaka/items/3fe39911e3f2479128e8
Reactの公式Docにも記載があるのですが、あるコンポーネントのレンダリング中に他のコンポーネントへHooksをトリガーしてはいけないとのこと。
https://ja.reactjs.org/blog/2020/02/26/react-v16.13.0.html#warnings-for-some-updates-during-render
私のケースでは、FuncBでのレンダリング中にFuncAのステートをHooksで更新しようとしたために発生していたエラーのようですね。
解決法についても記載があって、以下の通りFuncB中でのHooksのトリガーを、FuncBのレンダリングが終わってから実行すればOKです。具体的にどうやったらこれが実現できるかというと、ここでuseEffectの出番ですね・・!
この警告は、意図しない状態変更によって引き起こされるアプリケーションのバグを見つけるのに役立ちます。レンダーの結果として他のコンポーネントの状態を意図的に変更したいという稀なケースでは、
setState
呼び出しをuseEffect
にラップすることができます。
最終的に以下のようにコードを修正して、エラーが解消されました!
export const FuncA = () => {
const [value, setValue] = useState(0);
#################
const FuncB = () => {
useEffect(()=>{
setValue(1)
})
return (
・・・
)
}
#################
return (
・・・
);
};
なるほど、こんな制約もあるんですねぇ・・・勉強になりました。
それでは今回はこの辺りで。
最後までご覧いただきありがとうございました!
[番外編] ReactNativeをもっと学ぶなら・・・
React Nativeをもっとちゃんと学びたい!という方は、こちらにおすすめコンテンツをまとめましたので、ご参考にしていただければと思います・・!
土台のJavaScript/TypeScriptに不安がある方は、こちらもまとめましたので、ご参考になりましたら幸いです。
コメントを残す