问题描述
我正在使用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);
...
}