无法从Debounce中获取自定义钩子数据


import { debounce  } from 'lodash';
const App = () => {
const [text, setText] = useTestState();
const handleSearchKeyword = (keyword: string) => {
setText(keyword);
sendQuery();
};
const sendQuery = useCallback(
debounce(() => {
console.log(text);
}, 1000),
[]
);
return <input type="text" onChange={handleSearchKeyword} />;
};
const useTestState = () => {
const [text, setText] = useState('');
return [text, setText];
};

函数setData正常工作

然而,sendQuery函数

中打印null我想知道为什么它在debounce上不起作用

它不起作用,因为该函数是在text为空字符串的作用域中声明的。由于当text发生变化时,不再重新声明已删除的函数,因此它将始终显示原始值。

你可以在text改变的时候重新声明它,但是那样会增加分解,因为它要求函数是相同的,所以这个不起作用:

const sendQuery = useCallback(
debounce(() => {
console.log(text);
}, 1000),
[text] // creates a new function whenever text changes
);

在这种情况下,最简单的解决方案是将keyword作为参数传递给已拆分的函数:

const sendQuery = useCallback(
debounce(text => { // text is a parameter now
console.log(text);
}, 1000), []
);
const handleSearchKeyword = (keyword: string) => {
setText(keyword);
sendQuery(keyword); // pass keyword
};

这是React hooks FAQ中描述的过时的props/state问题。

一个好的解决方案是使用"最新状态";FAQ中描述的refboxing模式(搜索"最后的手段"):

import { debounce } from "lodash";
const App = () => {
const [text, setText] = useState("");
const latestText = React.useRef();
React.useEffect(() => {
latestText.current = text;
}, [text]);
const handleSearchKeyword = (keyword: string) => {
setText(keyword);
sendQuery();
};
const sendQuery = useCallback(
debounce(() => {
console.log(latestText.current);
}, 1000),
[],
);
return <input type="text" onChange={handleSearchKeyword} />;
};

如果你喜欢,可以把它捆绑到一个自定义钩子中:

function useStateWithLatest(initial) {
const [value, setValue] = useState(initial);
const latest = React.useRef(initial);
React.useEffect(() => {
latest.current = value;
}, [value]);
return [value, setValue, latest];
}
const App = () => {
const [text, setText, latestText] = useStateWithLatest("");
const handleSearchKeyword = (keyword: string) => {
setText(keyword);
sendQuery();
};
const sendQuery = useCallback(
debounce(() => {
console.log(latestText.current);
}, 1000),
[],
);
return <input type="text" onChange={handleSearchKeyword} />;
};

根据你当前的代码,sendQuery将使用相同的文本值,无论你设置了多少次,即useCallback的值是记忆的,因为你没有设置任何依赖关系。

你需要像这样将text作为useCallback的依赖项传递。

const handleSearchKeyword = (keyword: string) => {
setText(keyword);

debounce(sendQuery, 5000);
};
const sendQuery = useCallback(
() => {
console.log(text);
},
[text]
);

编辑:您可以在handleSearchKeyword函数中调用debounce,或者正如@Ori Drori指出的那样,只需将文本作为参数传递给debounce函数作用域以修复debounce

最新更新