[英]React and redux usage with async data fetching
我有这个动作
export function fetchBranches() {
return async dispatch => {
const result = await axios.get('https://localhost:5002/Branches')
dispatch({ type: FETCH_BRANCHES, payload: result.data.value })
}
}
和这样的减速机
export const branchReducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_BRANCHES: {
return { ...state, branches: action.payload }
}
default: return state
}
}
在我的组件中,我正在尝试做这样的事情
const dispatch = useDispatch()
dispatch(fetchBranches())
const branches = useSelector(state => state.branches.branches)
return <>
some component that uses branches
</>
所以我的问题是我收到了无数个尝试获取的请求(我可以在 redux 开发工具中看到它们)。 我的页面没有更新,但是如果 go 到其他页面然后返回到尝试执行此提取的页面,我可以在商店和页面上看到值。 所以问题是:
UPD:非常感谢您的回答,但我仍然看到我的组件在收到来自 api 的数据之前呈现的行为。 我想尝试useState
并在 useEffect 中设置useEffect
,但我不能使用useSelector
。 加载数据后,我应该怎么做才能重新渲染组件?
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))} />
)
}
调度通常不应该直接在渲染中完成,而是在useEffect
或事件回调中完成。 在你的情况下,
const dispatch = useDispatch()
useEffect(() => {
dispatch(fetchBranches());
},
[dispatch]
)
const branches = useSelector(state => state.branches.branches)
另请注意,您在这里写的是 redux 的相当旧的风格 - 请阅读官方教程以了解我们官方推荐的 redux 的推荐“现代”风格。 你最终会编写更少的代码。
您应该尝试将调度操作放入 useEffect 中,这样代码将只执行一次,如下所示:
const dispatch = useDispatch()
React.useEffect(() => {
dispatch(fetchBranches())
}, [])
文档在这里。
您的 HTTP 请求操作会导致组件中的副作用。 每个 state 更改都会导致重新渲染组件。 为避免副作用,您应该在组件中使用 useEffect 挂钩。
在您的组件中,
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
</>
您应该查看 Reactjs 文档以更好地了解 useEffect 挂钩。 https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects
将action
dispatch
到useEffect
挂钩以解决您的问题。
尝试:
useEffect(() => dispatch(fetchBranches()), [])
也许如果你试试这个:
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.