Reactjs React.useCallback未使用依赖项更新
我正在使用以下组件在我的应用程序中提交评论:Reactjs React.useCallback未使用依赖项更新,reactjs,react-hooks,Reactjs,React Hooks,我正在使用以下组件在我的应用程序中提交评论: const App = () => { const [text, setText] = React.useState(""); const send = React.useCallback(() => { setText(""); console.log("sending", text); }, [text]);
const App = () => {
const [text, setText] = React.useState("");
const send = React.useCallback(() => {
setText("");
console.log("sending", text);
}, [text]);
React.useEffect(() => {
const handler = e => {
switch (e.keyCode) {
case 13: // enter
if (e.shiftKey) {
e.preventDefault();
send();
}
break;
}
}
document.addEventListener("keydown", handler);
return () => document.removeEventListener("keydown", handler);
}, []);
return <div className="App">
<textarea
className="App__text"
value={text}
onChange={e => {
setText(e.target.value);
}} />
<button className="App__send" onClick={send}>send</button>
</div>;
};
const-App=()=>{
const[text,setText]=React.useState(“”);
const send=React.useCallback(()=>{
setText(“”);
console.log(“发送”,文本);
},[正文];
React.useffect(()=>{
常量处理程序=e=>{
开关(如钥匙代码){
案例13://输入
如果(如换档键){
e、 预防默认值();
send();
}
打破
}
}
文件。添加的文件列表器(“键控”,处理程序);
return()=>document.removeEventListener(“keydown”,handler);
}, []);
返回
{
setText(即目标值);
}} />
发送
;
};
这是一个简单的文本字段和按钮。当按下按钮或shift-enter键时,文本字段中的文本将发送到服务器(这里我们只是console.log
it)
该按钮工作正常-输入“hello world”
(或其他)按下按钮,控制台将显示hello world
但是,Shift-enter始终打印空字符串
我猜我误解了useCallback
。据我所知,useCallback
包装了您的函数。当其中一个依赖项发生更改时,React会在不更改包装器函数的情况下调出您的函数,因此无论在何处使用它,它仍然是最新的引用。鉴于在useffect
中调用的send
在作用域中似乎具有text
的初始值,但在按钮的onClick
中使用的是最新的,我的假设似乎不正确
我还尝试添加文本作为useffect
的依赖项,但是
- 我不想在每次击键时删除/创建/添加侦听器
- 它仍然缺少最后一个被按下的字符
如何将当前版本的send
函数保存在另一个回调函数中?如果依赖项中缺少send
,请查看此更新的代码:
React.useffect(()=>{
常量处理程序=e=>{
开关(如钥匙代码){
案例13://输入
如果(如换档键){
e、 预防默认值();
send();//这将始终被称为旧版本,而不是更新版本
}
打破
}
}
文件。添加的文件列表器(“键控”,处理程序);
return()=>document.removeEventListener(“keydown”,handler);
},[发送];//您需要将send放在这里,因为它是这个组件的一部分,需要更新
它使用它的原因是send
功能也会被记录:
const send=React.useCallback(()=>{
setText(“”);
console.log(“发送”,文本);
},[正文];
因此,您需要确保使用较新的文本更新到其较新的版本(这从未发生过,这就是为什么在SHIFT+ENTER中没有文本)
编辑:经过进一步调查,我认为最大的问题是文本和侦听器处理程序不同步
我已经修改了代码,将侦听器全部删除,并直接在textarea上使用onKeyDown
prop。看看这个工作代码笔:
您的依赖项中缺少send
,请查看此更新的代码:
React.useffect(()=>{
常量处理程序=e=>{
开关(如钥匙代码){
案例13://输入
如果(如换档键){
e、 预防默认值();
send();//这将始终被称为旧版本,而不是更新版本
}
打破
}
}
文件。添加的文件列表器(“键控”,处理程序);
return()=>document.removeEventListener(“keydown”,handler);
},[发送];//您需要将send放在这里,因为它是这个组件的一部分,需要更新
它使用它的原因是send
功能也会被记录:
const send=React.useCallback(()=>{
setText(“”);
console.log(“发送”,文本);
},[正文];
因此,您需要确保使用较新的文本更新到其较新的版本(这从未发生过,这就是为什么在SHIFT+ENTER中没有文本)
编辑:经过进一步调查,我认为最大的问题是文本和侦听器处理程序不同步
我已经修改了代码,将侦听器全部删除,并直接在textarea上使用onKeyDown
prop。看看这个工作代码笔:
这与使用文本作为依赖项具有相同的问题:(1)每次按键时,它都会删除/添加向下键回调(2)由于useffect
延迟1帧,最后一个字符总是被切断。另外,如果我只是使用send
作为依赖项,那么使用useCallback
有什么意义呢?如果您想记住难以计算的函数,并且只更新特定的更改,而不是任何更改,您应该useCallback
。我建议将useCallback
放在这里,要解决(1)个问题,您可以将其分为不同的useffects,我将使用更新答案example@SandyGifford我现在明白你的问题了,我已经花了一段时间摆弄代码,并设法找到了一些答案,看看我的代码。对我来说是个大麻烦。如果您没有事件驱动组件,我仍然认为这里有一个有趣的问题,但我想我将在另一个问题中发布它。谢谢所以,有趣的故事是,我使用了一个CodePen模板,我在hooks还在beta版时制作了这个模板,useEffect
在第一帧时没有被调用。这就是为什么