反应 useState:isActive 和 hasActivatedOnce 状态
React useState: isActive and hasActivatedOnce states
假设您有这 2 个状态:
const [ isActive ] = useState(false);
const [ hasActivatedOnce ] = useState(false);
例如,isActive
可能会跟踪元素的悬停状态。
然后 hasActivatedOnce
将跟踪该元素是否已经 hovered/activated 一次。所以它会转 true
一次,然后永远不会转 false
.
我正在尝试找出一种 clean/performant 方法来根据 isActive
状态更新 hasActivatedOnce
状态,即当 isActive
设置为 [=13 时=], hasActivatedOnce
应该设置为 true
(当然只重新渲染元素一次)。
您可以为此使用 useEffect:
const [ isActive ] = useState(false);
const [ hasActivatedOnce, setHasActivatedOnce ] = useState(false);
useEffect(() => {
if (isActive) {
setHasActivatedOnce(true);
}
}, [isActive])
使用相同的值多次调用“setHasActivatedOnce”不会触发渲染。
我不确定按照你的要求做有什么困难。如果我理解正确你可以像
那样实现它
const [isActive, setIsActive] = useState(false);
const [hasActivatedOnce, setHasActivatedOnce] = useState(false);
在你的 JSX 中,
<div onMouseOver={()=>{setIsActive(true);setHasActivatedOnce(true)}} onMouseOut={()=>{
setIsActive(false);
}}>
Something
</div>
JSX 可以是你喜欢的任何东西。由于您没有提供任何样本,我只使用了 div
从表面上看,这似乎是 useEffect:
的一个很好的用途
const [ isActive, setIsActive ] = useState(false);
const [ hasActivatedOnce, setHasActivatedOnce ] = useState(false);
useEffect(() => {
if (isActive) setHasActivatedOnce(true);
}, [isActive]);
此效果对 isActive
状态的变化作出反应,并在它为真时设置第二个状态。 React 摆脱了相同的状态更新,因此我们可以在 isActive
为真时安全地更新,而不会触发额外的重新渲染。
不过,我认为效果挂钩在这里有点矫枉过正,并且增加了不必要的复杂性。您也可以将两个 setter 包装在一个函数中,并在 isActive
需要更改时调用它:
const setIsActiveWithEffect = (bool) => {
setIsActive(bool);
if (bool) setHasActivatedOnce(true);
};
一个选项可以使用 useReducer 挂钩。它就像 useState 但它可以让你做一些复杂的操作,比如根据之前的状态进行计算。
你需要的是这样的:
import React, { useReducer } from 'react';
const reducer = (state, action) => {
switch(action.type){
case 'activate':
return {
isActive: action.payload.isActive,
hasActivated: action.payload.isActive || state.hasActivated
};
default:
return state;
}
};
const [state, dispatch] = useReducer(reducer,{isActive: false, hasActivated:false});
// Using in the component
<button onClick={() => dispatch({type: 'activate', payload:{isActive:true}})}>
如果你有更多的值相互依赖或者你需要一些复杂的逻辑,你可以使用useReducer。否则,我认为 中的第二个解决方案会更好。
假设您有这 2 个状态:
const [ isActive ] = useState(false);
const [ hasActivatedOnce ] = useState(false);
例如,isActive
可能会跟踪元素的悬停状态。
然后 hasActivatedOnce
将跟踪该元素是否已经 hovered/activated 一次。所以它会转 true
一次,然后永远不会转 false
.
我正在尝试找出一种 clean/performant 方法来根据 isActive
状态更新 hasActivatedOnce
状态,即当 isActive
设置为 [=13 时=], hasActivatedOnce
应该设置为 true
(当然只重新渲染元素一次)。
您可以为此使用 useEffect:
const [ isActive ] = useState(false);
const [ hasActivatedOnce, setHasActivatedOnce ] = useState(false);
useEffect(() => {
if (isActive) {
setHasActivatedOnce(true);
}
}, [isActive])
使用相同的值多次调用“setHasActivatedOnce”不会触发渲染。
我不确定按照你的要求做有什么困难。如果我理解正确你可以像
那样实现它const [isActive, setIsActive] = useState(false);
const [hasActivatedOnce, setHasActivatedOnce] = useState(false);
在你的 JSX 中,
<div onMouseOver={()=>{setIsActive(true);setHasActivatedOnce(true)}} onMouseOut={()=>{
setIsActive(false);
}}>
Something
</div>
JSX 可以是你喜欢的任何东西。由于您没有提供任何样本,我只使用了 div
从表面上看,这似乎是 useEffect:
的一个很好的用途const [ isActive, setIsActive ] = useState(false);
const [ hasActivatedOnce, setHasActivatedOnce ] = useState(false);
useEffect(() => {
if (isActive) setHasActivatedOnce(true);
}, [isActive]);
此效果对 isActive
状态的变化作出反应,并在它为真时设置第二个状态。 React 摆脱了相同的状态更新,因此我们可以在 isActive
为真时安全地更新,而不会触发额外的重新渲染。
不过,我认为效果挂钩在这里有点矫枉过正,并且增加了不必要的复杂性。您也可以将两个 setter 包装在一个函数中,并在 isActive
需要更改时调用它:
const setIsActiveWithEffect = (bool) => {
setIsActive(bool);
if (bool) setHasActivatedOnce(true);
};
一个选项可以使用 useReducer 挂钩。它就像 useState 但它可以让你做一些复杂的操作,比如根据之前的状态进行计算。
你需要的是这样的:
import React, { useReducer } from 'react';
const reducer = (state, action) => {
switch(action.type){
case 'activate':
return {
isActive: action.payload.isActive,
hasActivated: action.payload.isActive || state.hasActivated
};
default:
return state;
}
};
const [state, dispatch] = useReducer(reducer,{isActive: false, hasActivated:false});
// Using in the component
<button onClick={() => dispatch({type: 'activate', payload:{isActive:true}})}>
如果你有更多的值相互依赖或者你需要一些复杂的逻辑,你可以使用useReducer。否则,我认为