Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs React.useCallback未使用依赖项更新_Reactjs_React Hooks - Fatal编程技术网

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
在第一帧时没有被调用。这就是为什么