2019年9月11日水曜日

eslintルールのreact-hooks/exhaustive-depsを設定していると無限ループに陥った的なお話

  • このエントリーをはてなブックマークに追加

hooksは便利というかいい感じなわけで。
useStateとかuseCallbackとか色々とあるわけで。
その中で公式的にESLint入れるならばreact-hooks/exhaustive-depsとreact-hooks/rules-of-hooksを入れておけって言ってるんだけど、react-hooks/exhaustive-depsが悪さをしていたっていう。

ということで今日はreact-hooks/exhaustive-depsが悪さをするパターン的なお話をば。

function HogeScreen(props){
  const navigation = useNavigation();

  const articleId = navigation.getParam('id');
  const [article, setArticle] = useState(null);

  // getArticle
  useEffect(() => {
    fetch('https://...').then(r => setArticle(r));
  }, [articleId, navigation]);

  // setTitle
  useEffect(() => {
    if (article) {
      navigation.setParams({ title: article.title });
    }
  }, [article, navigation]);

  ...
}

例えばこういうパターン。
react-navigationのparamsとしてidを受け取って、それを元にAPIからデータをとってセットし(getArticle)、ページタイトルを設定する(setTitle)という流れ。
navigationが第二引数が入っているとタイトルをセットすると同時に、再びAPIからデータを取って、ページタイトルを設定する…と無限ループに陥ってしまう。
なので無限ループに陥らないためにもreact-hooks/exhaustive-depsを自分はオフにしている。
もちろんuseRef使ってprevPropsを保存するような形にして、それで比較して更新されていなければ何もしないという処理を加えれば大丈夫なんだけど、正直なところこれを入れるのはなかなか面倒。
むしろページを開いた瞬間にしか処理をしないものなので、なんで入れないといけないんだという気持ちにもなる。

とりあえずこんな感じでESLintとhooksを組み合わせるとたまに最悪なことになってしまうので要注意。
実際のところhooksをすすめてる人たちはこういうのはどう解決してるんだろうか?
ちなみにreact-navigationだけではなくwebのreactでもこのようなことは起きることはあると思う。
すすめてるけど結局使っていないのか、それともESLintを使わないのか、などなど色々と考えてしまうなぁ的なみたいな。

ってな感じでreact-hooks/exhaustive-depsをオンにする場合は気をつけましょう的な。
実際のところこういうパターンはいっぱいあるだろうし、何も気にせず入れてしまうと逆にパフォーマンスが落ちてしまうのでダメだよね的なみたいな。

0 件のコメント:

コメントを投稿

Adsense