[英]React and redux usage with async data fetching
I have this action我有这个动作
export function fetchBranches() {
return async dispatch => {
const result = await axios.get('https://localhost:5002/Branches')
dispatch({ type: FETCH_BRANCHES, payload: result.data.value })
}
}
and such reducer和这样的减速机
export const branchReducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_BRANCHES: {
return { ...state, branches: action.payload }
}
default: return state
}
}
In my component, I'm try to do such thing在我的组件中,我正在尝试做这样的事情
const dispatch = useDispatch()
dispatch(fetchBranches())
const branches = useSelector(state => state.branches.branches)
return <>
some component that uses branches
</>
So my problem is i'm getting infinite number of request trying to fetch (I can see them in redux dev tools).所以我的问题是我收到了无数个尝试获取的请求(我可以在 redux 开发工具中看到它们)。 My page are not getting updated, but if go to other page and then return to one that tries perform this fetch, I'm can see values in store and at the page.
我的页面没有更新,但是如果 go 到其他页面然后返回到尝试执行此提取的页面,我可以在商店和页面上看到值。 So questions are:
所以问题是:
UPD: Thanks a lot for your answers, but I still see behavior that my component rendered before I received data from api. UPD:非常感谢您的回答,但我仍然看到我的组件在收到来自 api 的数据之前呈现的行为。 I wanted to try
useState
and set state in useEffect
, but I can't use useSelector
.我想尝试
useState
并在 useEffect 中设置useEffect
,但我不能使用useSelector
。 What should I do to re-render component as soon as my data loaded?加载数据后,我应该怎么做才能重新渲染组件?
UPD2: now my component look like UPD2:现在我的组件看起来像
function BranchList() {
const [isLoaded, setIsLoaded] = useState(false)
const dispatch = useDispatch()
useEffect(() => {
dispatch(fetchBranches())
setIsLoaded(true)
}, [])
const branches = useSelector(state => state.branches.branches)
const headerNames = ["Id", "Name"]
if (!isLoaded) {
return <>Loading...</>
}
return (
<EditableTable
data={branches}
headerNames={headerNames}
onEditConfirm={(row) => dispatch(updateBranch(row))}
onDelete={(id) => dispatch(deleteBranch(id))} />
)
}
Dispatching generally should never be done directly in render, but in a useEffect
or an event callback.调度通常不应该直接在渲染中完成,而是在
useEffect
或事件回调中完成。 In your case,在你的情况下,
const dispatch = useDispatch()
useEffect(() => {
dispatch(fetchBranches());
},
[dispatch]
)
const branches = useSelector(state => state.branches.branches)
Also please note that you are writing a pretty old style of redux here - please read the official tutorials to learn the recommended "modern" style of redux we are officially recommending.另请注意,您在这里写的是 redux 的相当旧的风格 - 请阅读官方教程以了解我们官方推荐的 redux 的推荐“现代”风格。 You'll end up writing a lot less code.
你最终会编写更少的代码。
Your HTTP request action causes side effects in the component.您的 HTTP 请求操作会导致组件中的副作用。 Every state change causes re-rendering the component.
每个 state 更改都会导致重新渲染组件。 To avoid side effects, you should use useEffect hook in your component.
为避免副作用,您应该在组件中使用 useEffect 挂钩。
In your component,在您的组件中,
const dispatch = useDispatch()
const onFetchBranches = useCallback(() => dispatch(fetchBranches()), [dispatch]);
const branches = useSelector(state => state.branches.branches)
useEffect(() => {
onFetchBranches();
}, [onFetchBranches]);
return <>
some component that uses branches
</>
You should check Reactjs documentation to understand useEffect hook better.您应该查看 Reactjs 文档以更好地了解 useEffect 挂钩。 https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects
https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects
dispatch
an action
into useEffect
hook to solve your issue.将
action
dispatch
到useEffect
挂钩以解决您的问题。
Try:尝试:
useEffect(() => dispatch(fetchBranches()), [])
Perhaps if you try this:也许如果你试试这个:
function BranchList() {
const [isLoaded, setIsLoaded] = useState(false)
const dispatch = useDispatch()
useEffect(() => {
if(!isLoaded) {
dispatch(fetchBranches())
.then(() => setIsLoaded(true))
}
}, [isLoaded])
const branches = useSelector(state => state.branches.branches)
const headerNames = ["Id", "Name"]
if (!isLoaded) {
return <>Loading...</>
}
return (
<EditableTable
data={branches}
headerNames={headerNames}
onEditConfirm={(row) => dispatch(updateBranch(row))}
onDelete={(id) => dispatch(deleteBranch(id))} />
)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.