簡體   English   中英

React 和 redux 使用異步數據獲取

[英]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 到其他頁面然后返回到嘗試執行此提取的頁面,我可以在商店和頁面上看到值。 所以問題是:

  1. 我應該在哪里以及如何調度操作來獲取一些數據來呈現它?
  2. 為什么我收到這么多請求,我該如何解決?

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 dispatchuseEffect掛鈎以解決您的問題。

嘗試:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM