react-native - 带有 useEffect 钩子和 useSelector 的无限循环
问题描述
我的 React Native 应用程序中有一个标准化的 Redux 存储。
我的减速机的结构是:
{
byId: {},
allIds: []
}
在我的组件中,我使用useSelector
钩子获取 Redux 状态片段:
const categories = useSelector((state: AppState) =>
state.products.allIds.map((id) => state.categories.byId[id.toString()])
);
中的逻辑useSelector
只是将byId
对象转换为数组。
当我将categories
数组设置为依赖项时,会发生无限循环:
const [values, setValues] = useState<any[]>([]);
useEffect(() => {
setValues([{ id: 1 }]);
console.log("logging");
}, [categories]);
不知道是什么问题。我相信这useSelector
是将对象转换为数组的逻辑。
编辑:
完整的组件代码:
// React
import React, { useEffect, useState } from "react";
// React redux
import { useSelector } from "react-redux";
import { AppState } from "@reducers/rootReducer";
// Logic
import ProductsScreenLogic from "./ProductsScreen.logic";
// Common components
import ScreenView from "@common/screen/Screen.view";
// Components
import NewProductModalView from "@components/products/new-product-modal/NewProductModal.view";
import ProductsTabsView from "@components/products/products-tabs/ProductsTabs.view";
import ProductListView from "@components/products/products-list/ProductList.view";
import CategoryListView from "@components/products/category-list/CategoryList.view";
const ProductsScreenView: React.FC = () => {
const { displayProductList, setDisplayProductList, products } =
ProductsScreenLogic();
// Makes the categories ById object into an array of categories
const categories = useSelector((state: AppState) => state.categories.allIds.map((id) => state.categories.byId[id.toString()])
);
const [values, setValues] = useState<any[]>([]);
useEffect(() => {
setValues([{ id: 1 }]);
console.log("logging");
}, [categories]);
return (
<>
<NewProductModalView />
<ScreenView></ScreenView>
</>
);
};
export default ProductsScreenView;
解决方案
问题是您的选择器总是返回一个新的引用(因为调用map
)。您可以改为使用which 将记住它,并且仅在其中或createSelector
内部的某些内容发生更改时才返回新的引用:allIds
byId
const selectAllCategories = createSelector(
(state: AppState) => state.categories.allIds,
(state: AppState) => state.categories.byId,
(categoriesIds, categoriesById) => categoriesIds.map((id) => categoriesById[id.toString()])
);
但理想情况下,您应该避免使用这种遍历整个byId
对象的选择器,因为它有点否定了具有标准化状态的好处。您应该有一个只选择 的父组件,state.categories.allIds
然后将 id 作为道具传递给子组件,每个子组件都会选择自己的state.categories.byId[id]
. 这样,如果类别发生变化,只有相应的子组件会重新呈现,而不是让父组件和所有子组件重新呈现。
推荐阅读
- javascript - 在执行下一个在 NodeJS 中使用该数据的函数之前完成一个 readln 函数
- python-3.x - cv2.cvtColor 神秘地杀死了 python 工作者而不抛出异常
- python-3.x - .map 函数 Tensorflow 数据集出错
- ios - becomeFirstResponder() 没有调出键盘 - Swift 5 - iOS 14
- python - 将绘图函数链接到“plt.ax”
- c - 尝试打印队列时出现分段错误
- json - 解决“超过 30 次重定向”
- spring-cloud - Spring Cloud Gateway 路由不起作用,Hystrix Dashboard 加载崩溃
- nuxt.js - Nuxt Lang 属性配置
- android - Android:具有动态列数的列表视图