在 ReactJS 中结合 useState 和 useRef

M.S*_*.S. 2 reactjs react-hooks use-state

我有一些变量需要参考和状态。我在这里找到了一些对我有帮助的东西:/sf/answers/4084456421/

几乎它只是保持两个变量同步(伪代码):

const [track, setTrack] = useState('INIT');
const trackRef = useRef('INIT');

// Whenever changing, just both are updated
setTrack('newValue');
trackRef.current = 'newValue';
Run Code Online (Sandbox Code Playgroud)

我想知道将这两者结合成一个新的钩子是否有益。像这样的东西:

const useStateRef(initialState: any) {
  const [state, setState] = useState<typeof initialState>(initialState);
  const ref = useRef<typeof initialState>(initialState);

  useEffect(() => {
    setState(ref);
  }, [ref]);

  return [state, ref];
}
Run Code Online (Sandbox Code Playgroud)

最好的方法是什么?做这样的事情还很重要吗?

(背景是,我有一些自我重复的函数,需要引用来改变它们正在做的事情。但是当相同的变量发生变化时,我还需要状态变量来重新渲染可见的变化......也许有一个完全不同的函数这样做的方法,但我仍然对这种方法感到好奇。)

Cer*_*nce 6

这是可能的,但为了使类型正确,您应该使用泛型而不是any,并且需要反转效果钩子 -在更改ref.current时更改state。您还需要返回状态设置器,以便更改 的使用者中的值useStateRef

const useStateRef = <T extends unknown>(initialState: T) => {
  const [state, setState] = useState(initialState);
  const ref = useRef(initialState);

  useEffect(() => {
    ref.current = state;
  }, [state]);

  // Use "as const" below so the returned array is a proper tuple
  return [state, setState, ref] as const;
};
Run Code Online (Sandbox Code Playgroud)

或者,要同步更新,请删除效果挂钩:

if (ref.current !== state) ref.current = state;
Run Code Online (Sandbox Code Playgroud)

另请注意,永远不需要只包含原始类型的ref 。const trackRef = useRef('INIT');可以完全重构并替换为track. Refs 在处理对象(例如 HTMLElements)时通常很有用。