Javascript 反应钩子:从 useEffect 分派动作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/54930197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 05:15:11  来源:igfitidea点击:

React hooks: dispatch action from useEffect

javascriptreactjsreduxredux-saga

提问by HarshvardhanSharma

My folder structure:

我的文件夹结构:

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

I am refactoring my code to fetch data from API, using react hooks. I want to dispatch an action from useEffectin useFetching.jsthat is intercepted by sagamiddleware. The action should be dispatched only when the components(PageA, PageB, PageC) mount.

我正在重构我的代码以使用 react hooks从 API 获取数据。我想从useFetching.js中的useEffect调度一个被saga中间件拦截的动作。仅当组件(PageAPageBPageC)安装时才应分派该操作。

I am using redux, react-reduxand redux-saga.

我正在使用reduxreact-reduxredux-saga

PageA.js:

页面A.js:

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

Similar code for PageBand PageCcomponents.

PageBPageC组件的类似代码。

I have abstracted the reusable code to fetch data in useFetchingCustom hook.

我已经抽象了可重用的代码以在useFetchingCustom hook 中获取数据。

useFetching.js

使用Fetching.js

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

I don't know how to access redux dispatchin useFetching. I tried it with useReducereffect, but the sagas missed the action.

我不知道如何dispatchuseFetching 中访问 redux 。我试了一下,useReducer效果不错,但传奇错过了动作。

回答by Alex Hans

Version using react-redux hooks:

使用 react-redux 钩子的版本:

You can even cut out the connect function completely by using useDispatchfrom react-redux:

你甚至可以通过使用useDispatchfrom react-redux来完全切断连接功能:

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

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

with your custom hook

使用您的自定义挂钩

import { useDispatch } from 'react-redux';

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

Edit:removed dispatch from custom hook as suggested by @yonga-springfield

编辑:按照@yonga-springfield 的建议从自定义钩子中删除调度

Note:React guarantees that dispatch function identity is stable and won't change on re-renders. This is why it's safe to omit from the useEffect or useCallback dependency list.

注意:React 保证 dispatch 函数标识是稳定的并且不会在重新渲染时改变。这就是为什么从 useEffect 或 useCallback 依赖项列表中省略是安全的。

回答by markerikson

You would need to pass either bound action creators or a reference to dispatchto your hook. These would come from a connected component, same as you would normally use React-Redux:

您需要传递绑定动作创建者或dispatch对钩子的引用。这些将来自一个连接的组件,就像你通常使用 React-Redux 一样:

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

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

const mapDispatch = {
    fetchSomething
};

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

The hook should then call the bound action creator in the effect, which will dispatch the action accordingly.

然后钩子应该调用效果中的绑定动作创建者,这将相应地分派动作。

Also, note that your current hook will re-run the effect everytime the component is re-rendered, rather than just the first time. You'd need to modify the hook like this:

另外,请注意,每次重新渲染组件时,您当前的钩子都会重新运行效果,而不仅仅是第一次。您需要像这样修改钩子:

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

回答by yonga springfield

This is just to bring some optimization to @Alex Hans' answer.

这只是为了对@Alex Hans 的回答进行一些优化。

As per the documentation here. A custom Hook is a JavaScript function whose name starts with ”use” and that may call other Hooks.

根据此处的文档。自定义 Hook 是一个 JavaScript 函数,其名称以“use”开头,并且可以调用其他 Hook。

With this in mind, we need not send a reference to the dispatch function to the useFetching hook as a parameter but rather, simply not send it and rather simply use it from within the useFetching hook with the appropriate imports.

考虑到这一点,我们不需要将调度函数的引用作为参数发送到 useFetching 钩子,而是简单地不发送它,而是简单地从带有适当导入的 useFetching 钩子中使用它。

Here's an excerpt of what I mean.

这是我的意思的摘录。

import { useDispatch } from 'react-redux';

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

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

I can't ascertain this example will fit without errors in your codebase in your case but just trying to explain the idea/concept behind this post.

我无法确定这个示例是否适合您的代码库中没有错误,但只是试图解释这篇文章背后的想法/概念。

Hope this helps any future comer.

希望这对任何未来的人都有帮助。

回答by Asgar Ali Khachay

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 }));
 }