Leo*_*ang 6 javascript reactjs react-hooks
有一个常用的实用程序钩子“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 = ref.current.updateCount;
useLayoutEffect(() => {
ref.current.committedVal = ref.current.tempVal;
ref.current.updateCount++;
});
return {
get current() {
// tempVal is from new render, committedVal is from old render.
return ref.current.updateCount === startingUpdateCount
? ref.current.tempVal
: ref.current.committedVal;
},
set current(newVal: T) {
ref.current.tempVal = newVal;
},
};
}
Run Code Online (Sandbox Code Playgroud)
这还没有经过彻底的测试,只是在写这个问题的时候写的,但它似乎大部分时间都有效。它应该比上面的两个版本都好,但它有两个问题:它每次都返回一个不同的对象,并且在这种情况下仍然可能不一致:
渲染 1:
渲染 2:
function1 将使用 val1,但它应该使用 val2。
以下是我认为正确的:
const useLatest = <T extends any>(current: T) => {
const storedValue = React.useRef(current)
React.useLayoutEffect(() => {
storedValue.current = current
})
return storedValue.current
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
156 次 |
| 最近记录: |