Redux不断更新

问题描述

我正在使用expo使用React Native构建应用程序,并且实现了Redux。现在在我的组件中,我需要从API中获取一些内容以填充列表。我决定使用useEffect挂钩来完成该操作。现在,在我的useEffect钩子的依赖项数组中,放入了Redux状态列表。像这样:

const onFetchOrders = async (query: string,offset: number,limit?: number,filter?: {}) => {
  await props.fetchOrders('',0);

}

useEffect(() => {
  setIsLoading(true);
  onFetchOrders('',0);

  if (props.orders.length > 0) {
    setorders(props.orders)
  } else {
    setIsLoading(true);
  }

},[props.orders])

订单已映射到另一个组件中的道具:

const mapState = (state : RootState) => ({
    orders: state.orders.items,debtor: state.debtor.debtor,totalCount: state.orders.totalCount
})

const mapdispatch = (dispatch: any) => {
    return {
      fetchOrders: (query?: string,offset?: number,filters?: {}) => dispatch(tFetchOrders(query,offset,limit,filters)),fetchDebtor: (uuid: string) => dispatch(thunkFetchDebtor(uuid)),fetchCredentials: () => dispatch(thunkFetchCredentials()),};
  }

//const connector = connect(mapState,mapdispatch)(Root);
export const connector = connect(mapState,mapdispatch);

export type OrdersProps = ConnectedProps<typeof connector> & OrderStackNavProps<"Orders">;

现在,如果我启动该应用程序,则useEffect挂钩会不断重新渲染,因为orders数组中似乎有更新。

解决方法

您编写useEffect钩子的方式将在每次props.orders更改时运行,因为您在数组中传递了该prop作为可选参数。您可以在ReactJS文档here中详细了解useEffect的工作原理。

如果您希望useEffect挂钩在组件呈现时仅运行一次,则应传递一个空数组:

useEffect(() => {
  setIsLoading(true);
  onFetchOrders('',0);
},[]);

一旦开始提取,您就可以在另一个useEffect钩子中将订单添加到道具中:

useEffect(() => {
  if (props.orders.length > 0) {
    setIsLoading(false);
    setOrders(props.orders)
  } else {
    setIsLoading(true);
  }

},[props.orders])
,

useEffect每次在组件中的任何道具更改时运行。为了避免这种情况,并在useEffect数组中保留订单,可以使用destructuring assignment syntax

const { orders } = props // where the magic happens

useEffect(() => {
  setIsLoading(true);
  onFetchOrders('',0);

  if (orders.length > 0) {
    setOrders(orders)
  } else {
    setIsLoading(true);
  }

},[orders])

此代码现在仅在订单道具更改时运行,而在其他任何道具更改时运行。

此外,如果忘记提及,请查看useEffect infinite loop problem。您可以将useEffect挂钩与useCallback挂钩结合使用,以避免无限循环。

使用useCallback挂钩将要传递给useEffect挂钩的函数包装起来。然后在useEffect挂钩中调用包装的函数。这样可以避免useEffect中出现无限循环。

const loadCustomers = useCallback(async (query: string,offset: number,limit?: number,filter?: {}) => {
    await props.fetchOrders('',0);
    ...
}