web-dev-qa-db-ja.com

Reactフック:useEffectからのディスパッチアクション

私のフォルダ構造:

|--App
  |--Components
    |--PageA.js
    |--PageB.js
    |--PageC.js
  |--common-effects
    |--useFetching.js

React hooks を使用して、APIからデータをフェッチするようにコードをリファクタリングしています。 useEffectからuseFetching.jsのアクションをディスパッチしたいsagaミドルウェア。アクションは、components(PageAPageBPageC)マウント。

reduxreact-reduxおよびredux-saga

PageA.js

function(props) {
  useFetching(actionParams)
  //....//
}

PageBおよびPageCコンポーネントの同様のコード。

useFetchingCustom hookでデータをフェッチするための再利用可能なコードを抽象化しました。

useFetching.js

const useFetching = actionArgs => {
  useEffect( () => {
    store.dispatch(action(actionArgs)); // does not work
  })
}

useFetchingでredux dispatchにアクセスする方法がわかりません。 useReducer効果で試してみましたが、サガはアクションを逃しました。

10

バインドされたアクションの作成者またはdispatchへの参照をフックに渡す必要があります。これらは、通常React-Reduxを使用するのと同じように、接続されたコンポーネントから取得されます。

function MyComponent(props) {
    useFetching(props.fetchSomething);

    return <div>Doing some fetching!</div>
}

const mapDispatch = {
    fetchSomething
};

export default connect(null, mapDispatch)(MyComponent);

次に、フックはエフェクト内のバインドされたアクションクリエーターを呼び出す必要があり、それに応じてアクションがディスパッチされます。

また、現在のフックは、コンポーネントが再レンダリングされるたびに毎回エフェクトを再実行するだけでなく、再実行することにも注意してください。次のようにフックを変更する必要があります。

const useFetching = someFetchActionCreator => {
  useEffect( () => {
    someFetchActionCreator();
  }, [])
}
12
markerikson

React-reduxフックを使用したバージョン:

useDispatchをreact-reduxから使用することで、connect関数を完全に削除することもできます。

export default function MyComponent() {
  useFetching(fetchSomething);

  return <div>Doing some fetching!</div>
}

あなたのカスタムフックで

import { useDispatch } from 'react-redux';

const useFetching = (someFetchActionCreator) => {
  const dispatch = useDispatch();
  useEffect(() => {
    dispatch(someFetchActionCreator());
  }, [])
}

編集: @ yonga-springfieldの提案に従ってカスタムフックからディスパッチを削除

注: Reactは、ディスパッチ関数IDが安定していて、再レンダリング時に変更されないことを保証します。これが、useEffectまたはuseCallback依存関係リストから省略しても安全な理由です。 。

20
Alex Hans

これは、@ Alex Hansの回答を最適化するためのものです。

ドキュメントのとおり here 。カスタムフックは、名前が「use」で始まるJavaScript関数であり、他のフックを呼び出す場合があります。

これを念頭に置いて、ディスパッチ関数への参照をパラメーターとしてuseFetchingフックに送信する必要はなく、単に送信せず、適切なインポートを使用してuseFetchingフック内から単に使用するだけです。

これが私の意味の抜粋です。

import { useDispatch } from 'react-redux';

const useFetching = (someFetchActionCreator) => {
    const dispatch = useDispatch()

    useEffect(() => {
    dispatch(someFetchActionCreator());
  }, [])
}

この例があなたのケースのコードベースにエラーなしで収まるかどうかはわかりませんが、この投稿の背後にあるアイデア/コンセプトを説明しようとしています。

これが将来のどんな人にも役立つことを願っています。

3
useEffect(() => {
   fetchData();
 }, []);

 async function fetchData() {
   try {
     await Auth.currentSession();
     userHasAuthenticated(true);
   } catch (e) {
     if (e !== "No current user") {
       alert(e);
     }
   }
   dispatch(authentication({ type: "SET_AUTHING", payload: false }));
 }
0