Reactjs 使用React钩子管理按钮状态和结果处理

Reactjs 使用React钩子管理按钮状态和结果处理,reactjs,react-hooks,Reactjs,React Hooks,我有一些开关可以开/关。它们从父功能组件获取开/关状态。当用户切换状态时,我需要更新父级中的状态并运行函数 该函数使用所有切换的状态来过滤处于状态的项目列表,然后更改图形可视化组件中的渲染图形 目前,它们切换得很好,但渲染与按钮的状态不同步,因为处理函数最终以旧状态读取 我尝试使用useffect(),但由于该函数有很多依赖项,因此会导致循环 我尝试在自定义钩子中将useRef()与useState()耦合,以读取至少设置的最新筛选器组的当前状态,但也没有成功 对于如何以更好的方式重新构造代码,

我有一些开关可以开/关。它们从父功能组件获取开/关状态。当用户切换状态时,我需要更新父级中的状态并运行函数

该函数使用所有切换的状态来过滤处于状态的项目列表,然后更改图形可视化组件中的渲染图形

目前,它们切换得很好,但渲染与按钮的状态不同步,因为处理函数最终以旧状态读取

我尝试使用useffect(),但由于该函数有很多依赖项,因此会导致循环

我尝试在自定义钩子中将useRef()与useState()耦合,以读取至少设置的最新筛选器组的当前状态,但也没有成功

对于如何以更好的方式重新构造代码,或者对当前问题的潜在解决方案,有什么建议吗

执行过滤的Gross函数:

function filterItems(threshold, items = {}) {
    const { values } = kCoreResult;
    const { coloredItems } = rgRef.current;

    let itemsForUse;
    let filteredItems;

    if (Object.entries(items).length === 0 && items.constructor === Object) {
      itemsForUse = baseItemsRef.current;
    } else {
      itemsForUse = items;
    }

    const isWithinThreshold = id => has(values, id) && values[id] >= threshold;

    // filter for nodes meeting the kCoreValue criterion plus all links
    filteredItems = pickBy(
      itemsForUse,
      (item, id) => !isNode(item) || isWithinThreshold(id)
    );
    filteredItems = pickBy(
      filteredItems,
      item =>
        !has(item, 'data.icon_type') || !filterRef.current[item.data.icon_type]
    );

    setRg(rg => {
      rg.filteredItems = leftMerge(filteredItems, coloredItems);

      return {
        ...rg,
      };
    });

    setMenuData(menuData => {
      menuData.threshold = threshold;

      return {
        ...menuData,
      };
    });
  }
按下按钮后调用它的函数,该函数还更新按钮状态(按钮状态从过滤器对象向下传递):


似乎在处理程序中调用您的
filteriems
函数导致了陈旧状态错误,状态更新尚未协调。分离出更新状态的函数,并“侦听”状态更新以运行筛选函数

下面是一个有助于了解模式的演示:

export default function App() {
  const [filters, setFilters] = useState(filterOptions);

  const onChangeHandler = e => {
    setFilters({ ...filters, [e.target.name]: e.target.checked });
  };

  const filterItems = (threshold, items = {}) => {
    console.log("Gross function that does the filtering");
    console.log("threshold", threshold);
    console.log("items", items);
  };

  useEffect(() => {
    filterItems(42, filters);
  }, [filters]);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>

      {Object.entries(filters).map(([filter, checked]) => {
        return (
          <Fragment key={filter}>
            <label htmlFor={filter}>{filter}</label>
            <input
              id={filter}
              name={filter}
              type="checkbox"
              checked={checked}
              onChange={onChangeHandler}
            />
          </Fragment>
        );
      })}
    </div>
  );
}
导出默认函数App(){
常量[过滤器,设置过滤器]=使用状态(过滤器选项);
const onChangeHandler=e=>{
setFilters({…filters[e.target.name]:e.target.checked});
};
常量filterItems=(阈值,项={})=>{
log(“执行过滤的总函数”);
日志(“阈值”,阈值);
控制台日志(“项目”,项目);
};
useffect(()=>{
过滤器项目(42个,过滤器);
},[过滤器];
返回(
你好,代码沙盒
开始编辑,看看神奇的发生!
{Object.entries(filters.map)([filter,checked])=>{
返回(
{filter}
);
})}
);
}


这是通过从状态副作用中分离状态更新来实现的。处理程序通过总是返回一个新对象和下一个筛选器值来更新筛选器状态,并且当值更改为
筛选器时,effect hook会触发

嘿,这很有意义,非常感谢您的帮助。在本例中,如果threshold也是一种状态,比如:我如何解决“React Hook useffect有一个缺少的依赖项:'filteriems'。包括它或删除依赖项数组。(React hooks/deps)”问题?就像我在依赖项数组中添加了阈值一样,当它被更改时,我的应用程序将在不应该的时候运行此函数。用更新的
阈值更新了我的沙盒。啊,是的,所以在更新的沙盒中,当我们设置新阈值时,“执行过滤的总函数”再次运行,我相信这是我想要解决的最后一个难题。我想找到一个选项,可以实现同样的效果,但函数仅在过滤器更改时运行,而不是函数中的其他类似于阈值的状态。您能分享在什么条件下应该调用过滤器函数吗?当然,在本例中,如果有一种方法可以使函数仅在过滤器更改时运行,尽管它使用了阈值状态,但这将完全解决我的问题。
export default function App() {
  const [filters, setFilters] = useState(filterOptions);

  const onChangeHandler = e => {
    setFilters({ ...filters, [e.target.name]: e.target.checked });
  };

  const filterItems = (threshold, items = {}) => {
    console.log("Gross function that does the filtering");
    console.log("threshold", threshold);
    console.log("items", items);
  };

  useEffect(() => {
    filterItems(42, filters);
  }, [filters]);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>

      {Object.entries(filters).map(([filter, checked]) => {
        return (
          <Fragment key={filter}>
            <label htmlFor={filter}>{filter}</label>
            <input
              id={filter}
              name={filter}
              type="checkbox"
              checked={checked}
              onChange={onChangeHandler}
            />
          </Fragment>
        );
      })}
    </div>
  );
}