javascript - React 从父道具克隆对象在重新渲染时不断更新
问题描述
不知道修复是什么。我们从 API 中获取一组对象,并使用它在视图中创建数据。同时在一个子组件(过滤器)中,我想映射数据中的一个字段以创建我的过滤器类别。过滤器将使用参数从 API 调用新数据,并返回该数据并更新道具(我认为这是问题,因为这会使用过滤后的数据重新设置子组件以再次设置类别)。
我认为将数组放入 useEffect 会阻止它被更新。
这是我的过滤器组件中的当前 tsx:
const ExclusiveOffersFilters = (props: ExclusiveOffersFiltersProps): JSX.Element => {
const newFilters = JSON.parse(JSON.stringify(props.options)); // copy the object from props
let filterOffers;
useEffect(() => {
filterOffers = newFilters.map((item: any) => {
return { value: item.offerType, display: item.offerType };
});
console.log('filterOffers: ', filterOffers); // succesfully logs the filtered items.
}, []);
return (
<tr>
<th>
<Filter
options={filterOffers} // here filterOffers is undefined
alignRight={props.alignRight}
handleClick={props.handleFilterChange}
multiSelect={props.multiSelect}
selectedItems={props.selectedItems}
/>
</th>
</tr>
);
};
我也尝试过 const newFilters = [...props.options];
,newFilters = props.options.slice(0)
但这是同样的问题(智慧似乎是使用 JSON 解析/字符串化)。
在我的父组件中,我这样称呼孩子:
<ExclusiveOffersFilters handleFilterChange={props.handleFilterChange} options={props.options} />
如果我删除该useEffect
函数并仅更新过滤器,它将起作用,但是在选择一个过滤器后,应用程序会更新 api 调用,只接收过滤后的数据,因此过滤器中只设置了一个类别。我需要防止。
我需要一种方法来获取原始类别并冻结它们以防止更新。
编辑
这是我们的示例数据:
const data = [
{
offerId: 1,
partnerName: "Another offer 4",
imageUrl:
"https://www.auctsjpg-w263-h98-99382466814e33da0cfa3d5d2afd921c.jpg",
description:
"Save up to 10% on something. <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> <p>Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>",
header: "Save up to 10%",
enabled: true,
deleted: false,
offerType: "Motoring"
},
{
offerId: 0,
partnerName: "Amazing offer 4",
imageUrl: "https://www.cGen",
description:
"Save up to 20% off* your business insurance thanks to our partnership with<BR/> Churchill Expert. Simply visit the Churchill Expert web page and choose the<BR/> insurance product to suit your business.<BR/> Churchill Expert will automatically apply the discount to your premium for the<BR/>duration of your policy. <BR/><BR/>*Minimum premiums apply. Discount applies to NIG policies arranged by Churchill Expert <BR/>and underwritten by U K Insurance Limited.<BR/> Professional Indemnity excluded.",
header: "Save up to 20% off",
enabled: true,
deleted: false,
offerType: "Insurance"
},
{
offerId: 190,
partnerName: "Amazing offer 4",
imageUrl: "https://www.ch.Code=ExpertGen",
description:
"Save up to 20% off* your business insurance thanks to our partnership with<BR/> Churchill Expert. Simply visit the Churchill Expert web page and choose the<BR/> insurance product to suit your business.<BR/> Churchill Expert will automatically apply the discount to your premium for the<BR/>duration of your policy. <BR/><BR/>*Minimum premiums apply. Discount applies to NIG policies arranged by Churchill Expert <BR/>and underwritten by U K Insurance Limited.<BR/> Professional Indemnity excluded.",
header: "Save up to 20% off",
enabled: true,
deleted: true,
offerType: "Insurance"
}
];
export default data;
如果我们在 offerType = Motoring 上进行过滤,那么我们再次使用 Motoring 作为我们的过滤器调用我们的 api,这只会从上述数据中返回 1 条记录,但是现在我们的过滤器会更新并且只显示 1 个 Motoring 过滤器类别。
请参阅应用程序中的附加示例。
我已经在这里转储了大部分文件:https ://codesandbox.io/s/charming-sinoussi-l2iwh?file=/data.js:0-2061以及示例数据。我不知道这有多大帮助,当有这么多依赖项时,很难做出一个可行的例子。
父 index.tsx 处理所有 ajax api 调用并将数据传递到 props。ExclusiveOffersFilters.tsx 收到此信息并进行更新,这是我要停止的部分。正如@Adam 在评论中指出的那样,我们正在尝试解决这个问题,但我认为实际上父母很好,问题在于孩子。
我们确实想在应用程序的其他地方应用这个逻辑,所以性能会很好。我想知道我是否只需要不使用 props.options 并为此使用不同的道具?
解决方案
这就是你所需要的。如果遇到性能问题,请使用useMemo
. 如果您没有遇到性能问题,请不要做任何事情
const ExclusiveOffersFilters = (props: ExclusiveOffersFiltersProps): JSX.Element => {
const filters = props.options.map((item) => ({
value: item.offerType,
display: item.offerType
}));
return (
<tr>
<th>
<Filter
options={filters}
alignRight={props.alignRight}
handleClick={props.handleFilterChange}
multiSelect={props.multiSelect}
selectedItems={props.selectedItems}
/>
</th>
</tr>
);
};
示例useMemo
const filters = useMemo(() => props.options.map(....),[props.options]);
useMemo
除非您绝对确定自己需要它,否则我无法承受足够的压力。
推荐阅读
- javascript - 尽管处于不同的功能中,为什么它会陷入无限循环?
- angularjs - 如何使用angularjs从yml文件中获取数据
- c# - 如果参数为空,则排除条件
- wso2 - WSO2 文件连接器中的“被动模式”是什么?
- dart - 强制子类具有工厂方法
- sql - Oracle 12 SQL - ORA-00933、ORA-0923、ORA-00979 我做错了什么?
- angular - 为什么我无法在截获的请求中获取标头?
- javascript - 通过 XMLHttpRequest 读取响应流
- node.js - MongoDB查询多个集合
- javascript - Google Apps 脚本 <= 操作员问题