React hooks:从 useEffect 调度动作
React hooks: dispatch action from useEffect
我的文件夹结构:
|--App
|--Components
|--PageA.js
|--PageB.js
|--PageC.js
|--common-effects
|--useFetching.js
我正在重构我的代码以使用 React hooks 从 API 获取数据。
我想从 useEffect 在 useFetching.js 中发送一个被 saga 中间件拦截的动作.只有当组件(PageA, PageB, PageC) mount.
我正在使用 redux、react-redux 和 redux-saga。
PageA.js:
function(props) {
useFetching(actionParams)
//....//
}
PageB 和 PageC 组件的类似代码。
我已经抽象出可重用代码以在 useFetching
Custom hook.
中获取数据
useFetching.js
const useFetching = actionArgs => {
useEffect( () => {
store.dispatch(action(actionArgs)); // does not work
})
}
我不知道如何在 useFetching 中访问 redux dispatch
。我用 useReducer
效果试过了,但是 sagas 错过了动作。
您需要将绑定的动作创建者或对 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();
}, [])
}
使用 react-redux hooks 的版本:
你甚至可以通过使用 react-redux 中的 useDispatch
完全删除连接功能:
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 保证调度函数标识是稳定的并且不会在重新渲染时改变。这就是为什么可以安全地从 useEffect 或 useCallback 依赖项列表中省略的原因。
这只是为了对@Alex Hans 的回答进行一些优化。
根据文档 here。自定义 Hook 是一个 JavaScript 函数,其名称以“use”开头,可以调用其他 Hook。
考虑到这一点,我们不需要将对调度函数的引用作为参数发送到 useFetching 挂钩,而是简单地不发送它,而只是在 useFetching 挂钩中使用适当的导入来使用它。
这里摘录了我的意思。
import { useDispatch } from 'react-redux';
const useFetching = (someFetchActionCreator) => {
const dispatch = useDispatch()
useEffect(() => {
dispatch(someFetchActionCreator());
}, [])
}
我无法确定这个例子是否适合你的代码库,但只是想解释 post.
背后的 idea/concept
希望这对未来的任何人有所帮助。
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 }));
}
Alex Hans 对 dispatch 的正确决定,但要消除对 api 的请求循环,您可以指定对 dispatch 的依赖(我使用 Redux Toolkit )
import React, { useEffect } from 'react'
import { useDispatch } from 'react-redux'
import axios from 'axios'
import { getItemsStart, getItemsSuccess, getItemsFailure } from '../features/itemsSlice'
const fetchItems = () => async dispatch => {
try {
dispatch(getItemsStart());
const { data } = await axios.get('url/api')
dispatch(getItemsSuccess(data))
} catch (error) {
dispatch(getItemsFailure(error))
}
}
const PageA = () => {
const dispatch = useDispatch()
const { items } = useSelector(state => state.dataSlice)
useEffect(() => {
dispatch(fetchItems())
}, [dispatch])
return (
<ul>
{items.map(item => <li>{item.name}</li>}
</ul>
)
}
export default PageA
在 useEffect(() => {...}, [dispatch]) 中传递 dispatch 的依赖参数很重要
我的文件夹结构:
|--App
|--Components
|--PageA.js
|--PageB.js
|--PageC.js
|--common-effects
|--useFetching.js
我正在重构我的代码以使用 React hooks 从 API 获取数据。 我想从 useEffect 在 useFetching.js 中发送一个被 saga 中间件拦截的动作.只有当组件(PageA, PageB, PageC) mount.
我正在使用 redux、react-redux 和 redux-saga。
PageA.js:
function(props) {
useFetching(actionParams)
//....//
}
PageB 和 PageC 组件的类似代码。
我已经抽象出可重用代码以在 useFetching
Custom hook.
useFetching.js
const useFetching = actionArgs => {
useEffect( () => {
store.dispatch(action(actionArgs)); // does not work
})
}
我不知道如何在 useFetching 中访问 redux dispatch
。我用 useReducer
效果试过了,但是 sagas 错过了动作。
您需要将绑定的动作创建者或对 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();
}, [])
}
使用 react-redux hooks 的版本:
你甚至可以通过使用 react-redux 中的 useDispatch
完全删除连接功能:
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 保证调度函数标识是稳定的并且不会在重新渲染时改变。这就是为什么可以安全地从 useEffect 或 useCallback 依赖项列表中省略的原因。
这只是为了对@Alex Hans 的回答进行一些优化。
根据文档 here。自定义 Hook 是一个 JavaScript 函数,其名称以“use”开头,可以调用其他 Hook。
考虑到这一点,我们不需要将对调度函数的引用作为参数发送到 useFetching 挂钩,而是简单地不发送它,而只是在 useFetching 挂钩中使用适当的导入来使用它。
这里摘录了我的意思。
import { useDispatch } from 'react-redux';
const useFetching = (someFetchActionCreator) => {
const dispatch = useDispatch()
useEffect(() => {
dispatch(someFetchActionCreator());
}, [])
}
我无法确定这个例子是否适合你的代码库,但只是想解释 post.
背后的 idea/concept希望这对未来的任何人有所帮助。
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 }));
}
Alex Hans 对 dispatch 的正确决定,但要消除对 api 的请求循环,您可以指定对 dispatch 的依赖(我使用 Redux Toolkit )
import React, { useEffect } from 'react'
import { useDispatch } from 'react-redux'
import axios from 'axios'
import { getItemsStart, getItemsSuccess, getItemsFailure } from '../features/itemsSlice'
const fetchItems = () => async dispatch => {
try {
dispatch(getItemsStart());
const { data } = await axios.get('url/api')
dispatch(getItemsSuccess(data))
} catch (error) {
dispatch(getItemsFailure(error))
}
}
const PageA = () => {
const dispatch = useDispatch()
const { items } = useSelector(state => state.dataSlice)
useEffect(() => {
dispatch(fetchItems())
}, [dispatch])
return (
<ul>
{items.map(item => <li>{item.name}</li>}
</ul>
)
}
export default PageA
在 useEffect(() => {...}, [dispatch]) 中传递 dispatch 的依赖参数很重要