使用 React hooks 如何一起更新 2 个 hooks,但使用 prevState of one in other

With React hooks how to update 2 hooks together, but use prevState of one in other

在下面的代码中,当我调用 _toggleSearch 时,我同时更新了 2 个挂钩。

toggleSearchIsVisible 是一个简单的布尔值,但是,setActiveFilter 钩子必须在之前的 searchIsVisible 状态中传递。

我如何确定传入时其他状态尚未更新?或者我还应该如何重组一切?以前 setState 我可以很容易地通过以前的状态。

const [activeFilter, setActiveFilter] = useState('SHOW_ALL');
const [searchIsVisible, toggleSearchIsVisible] = useState(false);

const _toggleSearch = () => {
  setActiveFilter(searchIsVisible ? 'SHOW_SEARCH' : 'SHOW_ALL');
  toggleSearchIsVisible(!searchIsVisible);
};

我现在已经完成了:

const _toggleSearch = () => {
  if (searchIsActive) {
    setActiveFilter('SHOW_ALL');
    toggleSearchIsActive(false);
  } else {
    setActiveFilter('SHOW_SEARCH');
    toggleSearchIsActive(true);
    updateSearchValue('');
  }
};

感谢任何其他建议!

尝试使用 useEffect 钩子来处理切换 searchIsVisible 布尔值的副作用。

这是一个例子:

const _toggleSearch = () => {
  toggleSearchIsVisible(!searchIsVisible);
};

useEffect(() => {
  setActiveFilter(searchIsVisible ? 'SHOW_ALL' : 'SHOW_SEARCH');
}, [searchIsVisible]);

你可以看到我还把[searchIsVisible]传给了useEffect钩子来优化性能。

这将确保 useEffect 仅在 searchIsVisible 更新时触发:https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects


这是一个演示:https://codesandbox.io/s/l2901jr68l

希望对您有所帮助。

注:

另外我在你的条件中调换了 SHOW_ALLSHOW_SEARCH 的顺序,因为当 searchIsVisible 是 [=21= 时似乎应该显示 SHOW_SEARCH ],当 searchIsVisibletrue 时应显示 SHOW_ALL,但如果不是这种情况,只需将顺序切换回来。

如果您遇到同步两个状态的情况,请退后一步,看看是否可以从另一个状态派生出一个状态。看起来在这种情况下,你拥有的两个状态本质上是相关的,其中一个确实可以从另一个派生出来。所以你实际上不需要两个状态值,你只需要一个。派生状态不应该是状态的一部分,因为这会导致状态重复,然后您必须同步状态值,这就是您在问题中提出的问题。

在下面的示例中,我演示了如何使用 activeFiltersearchIsVisible 作为要保留的单一状态。

如果保留activeFilter,则searchIsVisible的值是从 派生的,反之亦然。关键是根据activeFilter.

的值设置searchIsVisible

activeFilter 作为州

const App = () => {
  const [activeFilter, setActiveFilter] = React.useState('SHOW_ALL');
  const searchIsVisible = activeFilter !== 'SHOW_ALL';

  const _toggleSearch = () => {
    setActiveFilter(activeFilter === 'SHOW_ALL' ? 'SHOW_SEARCH' : 'SHOW_ALL');
  };

  return (
    <div>
      <p>Active Filter: {activeFilter}</p>
      <button onClick={_toggleSearch}>Toggle Search</button>
      {searchIsVisible && <div>
        <input placeholder="Search" />
      </div>}
    </div>
  );
};

ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

searchIsVisible 作为状态

const App = () => {
  const [searchIsVisible, setSearchIsVisible] = React.useState(false);
  const activeFilter = searchIsVisible ? 'SHOW_SEARCH' : 'SHOW_ALL';

  const _toggleSearch = () => {
    setSearchIsVisible(!searchIsVisible);
  };

  return (
    <div>
      <p>Active Filter: {activeFilter}</p>
      <button onClick={_toggleSearch}>Toggle Search</button>
      {searchIsVisible && <div>
        <input placeholder="Search" />
      </div>}
    </div>
  );
};

ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>