反应 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”不会触发渲染。

https://reactjs.org/docs/hooks-effect.html

我不确定按照你的要求做有什么困难。如果我理解正确你可以像

那样实现它
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。否则,我认为 中的第二个解决方案会更好。