reactjs - React.useCallback 不更新依赖
问题描述
我正在使用以下组件在我的应用程序中提交评论:
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>;
};
这是一个简单的文本字段和按钮。当按下按钮或 shift-enter 时,文本字段中的文本被发送到服务器(这里我们只是console.log
它)。
该按钮工作正常 - 输入"hello world"
(或其他)按下按钮,控制台会说hello world
.
然而,Shift-enter 总是打印一个空字符串。
我猜我误会了useCallback
。据我了解,useCallback
包装你的功能。当其中一个依赖项发生变化时,React 会在不更改包装函数的情况下换出你的函数,因此无论在何处使用它,它仍然是最新的参考。鉴于send
被调用useEffect
的初始值似乎text
在范围内,但在onClick
of中使用的值button
是最新的,我的假设似乎不正确。
我也尝试添加text
作为useEffect
但是的依赖项
- 我不想在每次击键时删除/创建/添加侦听器,并且
- 无论如何,它仍然缺少按下的最后一个字符。
如何将我的send
函数的当前版本保留在另一个回调中?
解决方案
您缺少send
依赖项,请查看此更新后的代码:
React.useEffect(() => {
const handler = e => {
switch (e.keyCode) {
case 13: // enter
if (e.shiftKey) {
e.preventDefault();
send(); // This will always be called an older version, instead of updated one
}
break;
}
}
document.addEventListener("keydown", handler);
return () => document.removeEventListener("keydown", handler);
}, [send]); // You need to put send here, since it is part of this component, and needs to be updated
它与它一起工作的原因是因为send
函数也被记住了:
const send = React.useCallback(() => {
setText("");
console.log("sending", text);
}, [text]);
所以你需要确保更新到它的新版本,它的新文本(这从未发生过,这就是你的 SHIFT+ENTER 中没有文本的原因)
编辑:经过进一步调查,在我看来,最大的问题是不同步的 text 和 listener handler。
我已经修改了代码以使其工作,通过一起删除侦听器,并onKeyDown
直接在 textarea 上使用 prop。看看这个工作的codepen:
推荐阅读
- c# - 将值从另一个应用程序调用的 web 服务传递到 asp.net 网站
- spring - 如何使用 Junit 5 在 Spring boot 2.1.0.M4 中使用 @DataJpaTest 测试 Spring CrudRepository
- javascript - 如何更改 Angular 应用程序中占位符的字体大小?我在我的应用程序中使用正式的 ngx
- javascript - 如何将 Ajax 响应分配给 React 中另一个函数中的变量?
- regex - Express Regex 从路由中排除文件
- joomla - Joomla 3.8 - 无法批准用户注册
- c# - “RouteCollection”不包含“MapRoute”的定义,也没有可访问的扩展方法“MapRoute”
- android - 如何在 CustomLayoutManager 上保存/恢复值?
- swift - 后台线程中的 moya 请求
- git - 导出提交,包括注释