下面是一个可变 ref 的示例,该示例存储来自Overreacted 博客的当前回调:
function useInterval(callback, delay) {
const savedCallback = useRef();
// update ref before 2nd effect
useEffect(() => {
savedCallback.current = callback; // save the callback in a mutable ref
});
useEffect(() => {
function tick() {
// can always access the most recent callback value without callback dep
savedCallback.current();
}
let id = setInterval(tick, delay);
return () => clearInterval(id);
}, [delay]);
}
Run Code Online (Sandbox Code Playgroud)
然而,React Hook FAQ 指出不推荐使用该模式:
另请注意,此模式可能会导致并发模式出现问题。[...]
在任何一种情况下,我们都不推荐这种模式,只是为了完整起见在这里展示它。
我发现这种模式对于回调非常有用,但我不明白为什么它会在 FAQ 中出现危险信号。例如,客户端组件可以使用 …
在这个GitHub问题中,我基本上建议更改:
x = useCallback( ... , []);
Run Code Online (Sandbox Code Playgroud)
至:
x = useRef( ... ).current;
Run Code Online (Sandbox Code Playgroud)
两者相同,但是使用useRefReact不会比较依赖关系。
为此,有一个问题的答复:
有没有一种情况,没有依赖的useMemo或useCallback比useRef更好的选择?
我想不出一个,但我可能忽略了一些用例。
那么有人能想到这种情况吗?
有一个常用的实用程序钩子“useLatest”,它返回一个包含输入的最新值的引用。有两种常见的实现:
const useLatest = <T>(value: T): { readonly current: T } => {
const ref = useRef(value);
ref.current = value;
return ref;
};
Run Code Online (Sandbox Code Playgroud)
来自https://github.com/streamich/react-use/blob/master/src/useLatest.ts
const useLatest = <T extends any>(current: T) => {
const storedValue = React.useRef(current)
React.useEffect(() => {
storedValue.current = current
})
return storedValue
}
Run Code Online (Sandbox Code Playgroud)
来自https://github.com/jaredLunde/react-hook/blob/master/packages/latest/src/index.tsx
第一个版本不适合 React 18 的并发模式,如果在useEffect运行之前(例如在渲染期间)使用,第二个版本将返回旧值。
有没有办法实现既安全又一致返回正确值的方法?
这是我的尝试:
function useLatest<T>(val: T): React.MutableRefObject<T> {
const ref = useRef({
tempVal: val,
committedVal: val,
updateCount: 0,
});
ref.current.tempVal = val;
const startingUpdateCount = …Run Code Online (Sandbox Code Playgroud)