自定义反应挂钩的奇怪行为

时间:2019-08-27 13:49:41

标签: reactjs react-hooks

https://jsfiddle.net/dqx7kb91/1/

在这个小提琴中,我提取了一部分项目(我试图在不破坏任何内容的情况下尽可能地简化它),用于管理搜索过滤器。 我们将许多不同类型的过滤器定义为这样的对象:

/service

芯片组件用于列出所有已激活的过滤器并编辑已激活的过滤器(在这种情况下,请从已激活的过滤器列表中删除该过滤器)。

过滤器包含在一个对象中,该对象由包含自定义钩子的唯一容器处理。

问题是,假设我设置了第一个过滤器,然后设置了第二个过滤器,然后我决定最终删除第一个过滤器,两个过滤器均被删除。除此之外,一切都很好。

可能是什么原因造成的?在我看来,在我使用的自定义钩子useMap中,当我尝试删除过滤器时,它没有考虑实际的当前状态,而是使用了添加第一个过滤器时的状态(一个空对象) ,因此它会尝试从中删除所有内容并将状态设置为结果,即一个空对象。

我该如何解决?谢谢

1 个答案:

答案 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);