https://jsfiddle.net/dqx7kb91/1/
在这个小提琴中,我提取了一部分项目(我试图在不破坏任何内容的情况下尽可能地简化它),用于管理搜索过滤器。 我们将许多不同类型的过滤器定义为这样的对象:
/service
芯片组件用于列出所有已激活的过滤器并编辑已激活的过滤器(在这种情况下,请从已激活的过滤器列表中删除该过滤器)。
过滤器包含在一个对象中,该对象由包含自定义钩子的唯一容器处理。
问题是,假设我设置了第一个过滤器,然后设置了第二个过滤器,然后我决定最终删除第一个过滤器,两个过滤器均被删除。除此之外,一切都很好。
可能是什么原因造成的?在我看来,在我使用的自定义钩子useMap中,当我尝试删除过滤器时,它没有考虑实际的当前状态,而是使用了添加第一个过滤器时的状态(一个空对象) ,因此它会尝试从中删除所有内容并将状态设置为结果,即一个空对象。
我该如何解决?谢谢
答案 0 :(得分:0)
发生的事情是,当您设置第一个过滤器(假设为#1)时,您正在设置的map
仅包含过滤器1。设置了#2时,map
包含了过滤器#1和# 2。但是...这就是问题...过滤器#1的remove回调具有仅包含#1而不包含#2的映射。那是因为您的回叫是在设置过滤器#2之前设置的。通常可以解决此问题,因为您正在使用诸如useCallback之类的钩子,但是在实现它们的方式(createContainer(useFilters)
)中,您正在为每个过滤器对象创建单独的钩子。
我会将其简化为仅一个组件,一旦它开始工作,如果您确实需要,就开始一个接一个地提取片段。
我知道这是对您所写内容的完整重写,但这可行:
import React from "react";
import ReactDOM from "react-dom";
const App = () => {
const [map, setMap] = React.useState({});
// const get = React.useCallback(key => map[key], [map])
const set = (key, entry) => {
setMap({ ...map, [key]: entry });
};
const remove = key => {
const {[key]: omit, ...rest} = map;
setMap(rest);
};
// const reset = () => setMap({});
const filters = [
{ name: 'filter1', value: 1 },
{ name: 'filter2', value: 2 },
];
return (
<>
{Object.keys(map).map(key => (
<button onClick={() => remove(key)}>
REMOVE {key}
</button>
))}
<hr />
{filters.map(({ name, value }) => (
<button onClick={() => set(name, { value })}>
SET {name}
</button>
))}
</>
)
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);