繁体   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