[英]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.