https://jsfiddle.net/dqx7kb91/1/
在这个小提琴中,我提取了一个项目的一部分(我试图在不破坏任何东西的情况下尽可能简化它),用于管理搜索过滤器。 我们有许多不同类型的过滤器定义为一个对象,如下所示:
filter = {
name: "",
initVal: 1, //default value for the filter,
controlChip: ... // filter's chip component
...
}
芯片组件用于列出所有激活的过滤器并编辑已激活的过滤器(在这种情况下,从激活的过滤器列表中删除过滤器)。
筛选器包含在由包含自定义挂钩的唯一容器处理的对象中。
问题是,假设我设置了第一个过滤器,然后设置了第二个过滤器,我决定最终删除第一个过滤器,两个过滤器都被删除了。除此之外,一切都很好。
可能是什么原因造成的?在我看来,在我使用的自定义钩子useMap中,当我尝试删除过滤器时,它没有考虑实际的当前状态,而是使用我添加第一个过滤器(空对象)时的状态,因此它尝试从无到有中删除某些内容并将状态设置为结果, 一个空对象。
我该如何解决这个问题?谢谢
当您设置第一个过滤器(假设 #1)时,您正在设置仅包含过滤器 1 的map
。当您设置过滤器#2时,map
包含过滤器#1和#2。但。。。事情是这样的...过滤器 #1 的删除回调的映射仅包含 #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);