不知道解决这个问题的方法是什么。我们从 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 并为此使用不同的道具?
答案 0 :(得分:0)
useEffect
执行异步操作,因此 filterOffers
可以在渲染时未定义。
如果您想根据某个其他值创建一个值并希望对其进行优化,请使用 useMemo
钩子。
如果您想在组件的重新渲染之间存储一个值,请使用 useRef
钩子。
const newFilters = useRef(JSON.parse(JSON.stringify(props.options))); // copy the object from props
const filterOffers = useMemo(() => {
filterOffers = newFilters.current.map((item: any) => {
return { value: item.offerType, display: item.offerType };
});
console.log('filterOffers: ', filterOffers); // succesfully logs the filtered items.
}, [newFilters]);
答案 1 :(得分:0)
这就是你所需要的。如果遇到性能问题,请使用 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
。