使用 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_ALL
和 SHOW_SEARCH
的顺序,因为当 searchIsVisible
是 [=21= 时似乎应该显示 SHOW_SEARCH
],当 searchIsVisible
为 true
时应显示 SHOW_ALL
,但如果不是这种情况,只需将顺序切换回来。
如果您遇到同步两个状态的情况,请退后一步,看看是否可以从另一个状态派生出一个状态。看起来在这种情况下,你拥有的两个状态本质上是相关的,其中一个确实可以从另一个派生出来。所以你实际上不需要两个状态值,你只需要一个。派生状态不应该是状态的一部分,因为这会导致状态重复,然后您必须同步状态值,这就是您在问题中提出的问题。
在下面的示例中,我演示了如何使用 activeFilter
或 searchIsVisible
作为要保留的单一状态。
如果保留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>
在下面的代码中,当我调用 _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_ALL
和 SHOW_SEARCH
的顺序,因为当 searchIsVisible
是 [=21= 时似乎应该显示 SHOW_SEARCH
],当 searchIsVisible
为 true
时应显示 SHOW_ALL
,但如果不是这种情况,只需将顺序切换回来。
如果您遇到同步两个状态的情况,请退后一步,看看是否可以从另一个状态派生出一个状态。看起来在这种情况下,你拥有的两个状态本质上是相关的,其中一个确实可以从另一个派生出来。所以你实际上不需要两个状态值,你只需要一个。派生状态不应该是状态的一部分,因为这会导致状态重复,然后您必须同步状态值,这就是您在问题中提出的问题。
在下面的示例中,我演示了如何使用 activeFilter
或 searchIsVisible
作为要保留的单一状态。
如果保留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>