回调时过时的自定义挂钩状态 属性
Stale custom hook state property on callback
我的 React 应用程序中有一个自定义挂钩,它公开了一个函数 (hookFn
) 来计算 value
。一旦更新了值(状态更改、触发 useEffect),挂钩就会通过回调函数提醒应用程序。问题是:在我的回调函数中,我希望能够通过 hook.value
访问该值,但它似乎已经过时了!尽管我知道值状态已更新!
Codesandbox:https://codesandbox.io/s/stoic-payne-bwp6j5?file=/src/App.js:0-910
import { useEffect, useRef, useState } from "react";
export default function App() {
const hook = useCustomHook();
useEffect(() => {
hook.hookFn(hookCallback);
}, []);
function hookCallback(value) {
console.log({givenValue: value, hookValue: hook.value});
}
return "See console for output";
}
function useCustomHook() {
const callbackRef = useRef(null);
const [value, setValue] = useState("initial value");
useEffect(() => {
if (callbackRef.current) {
callbackRef.current(value);
}
}, [value]);
function hookFn(callbackFn) {
callbackRef.current = callbackFn;
setValue("value set in hookFn");
}
return { hookFn, value };
}
仅供参考:在我的实际应用中,该挂钩用于搜索,随着更多搜索结果可用,它可能会多次调用回调函数。
有什么方法可以确保hook.value
有效吗?还是一般情况下挂钩公开状态变量是不好的做法?
事实证明 hook.value
是陈旧的,因为当我从 hookCallback
访问它时 hook
是陈旧的。每次在我的自定义挂钩中发生状态更改时,useCustomHook
都会生成一个新对象。
然后,复杂的解决方案是为 hook
创建一个 ref
并在 useEffect
中保持最新。但是我必须确保在访问 hookRef.current.value
之前等待 useEffect
到 运行...这是我尝试完成这项工作的尝试:https://codesandbox.io/s/dazzling-shirley-0r7k47?file=/src/App.js
但是,更好的解决方案是:不要混合 React 状态和手动回调。 相反,只需观察 useEffect
中的状态变化,如下所示:
import { useEffect, useState } from "react";
export default function App() {
const hook = useCustomHook();
useEffect(() => {
hook.hookFn();
}, []);
useEffect(() => {
if (hook.value) console.log({ hookValue: hook.value });
}, [hook.value]);
return "See console for output";
}
function useCustomHook() {
const [value, setValue] = useState("initial value");
function hookFn(callbackFn) {
setValue("value set in hookFn");
}
return { hookFn, value };
}
请注意代码已简化,无需担心状态为 out-of-sync。
我的 React 应用程序中有一个自定义挂钩,它公开了一个函数 (hookFn
) 来计算 value
。一旦更新了值(状态更改、触发 useEffect),挂钩就会通过回调函数提醒应用程序。问题是:在我的回调函数中,我希望能够通过 hook.value
访问该值,但它似乎已经过时了!尽管我知道值状态已更新!
Codesandbox:https://codesandbox.io/s/stoic-payne-bwp6j5?file=/src/App.js:0-910
import { useEffect, useRef, useState } from "react";
export default function App() {
const hook = useCustomHook();
useEffect(() => {
hook.hookFn(hookCallback);
}, []);
function hookCallback(value) {
console.log({givenValue: value, hookValue: hook.value});
}
return "See console for output";
}
function useCustomHook() {
const callbackRef = useRef(null);
const [value, setValue] = useState("initial value");
useEffect(() => {
if (callbackRef.current) {
callbackRef.current(value);
}
}, [value]);
function hookFn(callbackFn) {
callbackRef.current = callbackFn;
setValue("value set in hookFn");
}
return { hookFn, value };
}
仅供参考:在我的实际应用中,该挂钩用于搜索,随着更多搜索结果可用,它可能会多次调用回调函数。
有什么方法可以确保hook.value
有效吗?还是一般情况下挂钩公开状态变量是不好的做法?
事实证明 hook.value
是陈旧的,因为当我从 hookCallback
访问它时 hook
是陈旧的。每次在我的自定义挂钩中发生状态更改时,useCustomHook
都会生成一个新对象。
然后,复杂的解决方案是为 hook
创建一个 ref
并在 useEffect
中保持最新。但是我必须确保在访问 hookRef.current.value
之前等待 useEffect
到 运行...这是我尝试完成这项工作的尝试:https://codesandbox.io/s/dazzling-shirley-0r7k47?file=/src/App.js
但是,更好的解决方案是:不要混合 React 状态和手动回调。 相反,只需观察 useEffect
中的状态变化,如下所示:
import { useEffect, useState } from "react";
export default function App() {
const hook = useCustomHook();
useEffect(() => {
hook.hookFn();
}, []);
useEffect(() => {
if (hook.value) console.log({ hookValue: hook.value });
}, [hook.value]);
return "See console for output";
}
function useCustomHook() {
const [value, setValue] = useState("initial value");
function hookFn(callbackFn) {
setValue("value set in hookFn");
}
return { hookFn, value };
}
请注意代码已简化,无需担心状态为 out-of-sync。