Javascript 如何使用useEffect挂钩注册事件?
我正在学习如何使用挂钩注册事件的课程,讲师给出了以下代码:Javascript 如何使用useEffect挂钩注册事件?,javascript,reactjs,react-native,react-hooks,Javascript,Reactjs,React Native,React Hooks,我正在学习如何使用挂钩注册事件的课程,讲师给出了以下代码: const[userText,setUserText]=useState(“”); const handleUserKeyPress=事件=>{ const{key,keyCode}=事件; 如果(keyCode==32 | |(keyCode>=65&&keyCode{ window.addEventListener('keydown',handleUserKeyPress); return()=>{ window.removeEve
const[userText,setUserText]=useState(“”);
const handleUserKeyPress=事件=>{
const{key,keyCode}=事件;
如果(keyCode==32 | |(keyCode>=65&&keyCode{
window.addEventListener('keydown',handleUserKeyPress);
return()=>{
window.removeEventListener('keydown',handleUserKeyPress);
};
});
返回(
自由打字!
{userText}
);
现在它工作得很好,但我不相信这是正确的方式。原因是,如果我理解正确,在每次重新渲染时,事件都会不断注册和注销,我认为这不是正确的方式
所以我对下面的useffect
钩子做了一点修改
useffect(()=>{
window.addEventListener('keydown',handleUserKeyPress);
return()=>{
window.removeEventListener('keydown',handleUserKeyPress);
};
}, []);
通过使用空数组作为第二个参数,让组件只运行一次效果,模仿componentDidMount
。当我尝试结果时,奇怪的是,在我键入的每个键上,它不是附加,而是被覆盖
我希望setUserText(${userText}${key}
);将新类型的键附加到当前状态并设置为新状态,但相反,它会忘记旧状态并用新状态重写
在第二种方法中,
useffect
只绑定一次,因此,userText
永远不会更新。一种方法是在ev上维护一个随userText
对象一起更新的局部变量埃利按键
const [userText, setUserText] = useState('');
let local_text = userText
const handleUserKeyPress = event => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
local_text = `${userText}${key}`;
setUserText(local_text);
}
};
useEffect(() => {
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, []);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
const[userText,setUserText]=useState(“”);
让本地_text=userText
const handleUserKeyPress=事件=>{
const{key,keyCode}=事件;
如果(keyCode==32 | |(keyCode>=65&&keyCode{
window.addEventListener('keydown',handleUserKeyPress);
return()=>{
window.removeEventListener('keydown',handleUserKeyPress);
};
}, []);
返回(
自由打字!
{userText}
);
就我个人而言,我不喜欢这个解决方案,觉得反反应
,我认为第一种方法已经足够好了,而且是专门为这种方式设计的。新答案:
useEffect(() => {
function handlekeydownEvent(event) {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}
document.addEventListener('keyup', handlekeydownEvent)
return () => {
document.removeEventListener('keyup', handlekeydownEvent)
}
}, [])
因为在useffect()
方法中,它取决于userText
变量,但您不将它放在第二个参数中,否则userText
将始终绑定到带有参数[]
的初始值'
您不需要这样做,只想让您知道第二个解决方案不起作用的原因。您需要一种方法来跟踪以前的状态。
useState
只帮助您跟踪当前状态。从中,可以使用另一个钩子访问旧状态
const prevRef = useRef();
useEffect(() => {
prevRef.current = userText;
});
我已经更新了你的例子来使用这个。它是有效的
const{useState,useffect,useRef}=React;
常量应用=()=>{
const[userText,setUserText]=useState(“”);
const prevRef=useRef();
useffect(()=>{
prevRef.current=用户文本;
});
const handleUserKeyPress=事件=>{
const{key,keyCode}=事件;
如果(keyCode==32 | |(keyCode>=65&&keyCode{
window.addEventListener(“向下键”,handleUserKeyPress);
return()=>{
window.removeEventListener(“向下键”,handleUserKeyPress);
};
}, []);
返回(
自由打字!
{userText}
);
};
ReactDOM.render(,document.getElementById(“根”);
对于您的用例,
useffect
需要依赖关系数组来跟踪更改,并根据依赖关系确定是否重新呈现。建议始终将依赖关系数组传递给useffect
。请参阅下面的代码:
我已经介绍了useCallback
hook
const { useCallback, useState, useEffect } = React;
const [userText, setUserText] = useState("");
const handleUserKeyPress = useCallback(event => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener("keydown", handleUserKeyPress);
return () => {
window.removeEventListener("keydown", handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<blockquote>{userText}</blockquote>
</div>
);
const{useCallback,useState,useffect}=React;
const[userText,setUserText]=useState(“”);
const handleUserKeyPress=useCallback(事件=>{
const{key,keyCode}=事件;
如果(keyCode==32 | |(keyCode>=65&&keyCode`${prevUserText}${key}`);
}
}, []);
useffect(()=>{
window.addEventListener(“向下键”,handleUserKeyPress);
return()=>{
window.removeEventListener(“向下键”,handleUserKeyPress);
};
},[handleUserKeyPress]);
返回(
{userText}
);
您无权访问已更改的useText状态。您可以将其复制到prevState。将状态存储在变量中,例如:state like so:
const App = () => {
const [userText, setUserText] = useState('');
useEffect(() => {
let state = ''
const handleUserKeyPress = event => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
state += `${key}`
setUserText(state);
}
};
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, []);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
};
const-App=()=>{
const[userText,setUserText]=useState(“”);
useffect(()=>{
让状态=“”
const handleUserKeyPress=事件=>{
const{key,keyCode}=事件;
如果(keyCode==32 | |(keyCode>=65&&keyCode{
window.removeEventListener('keydown',handleUserKeyPress);
};
}, []);
返回(
自由打字!
{userText}
);
};
处理此类场景的最佳方法是查看您在事件处理程序中执行的操作。如果您只是使用前一个状态设置状态,则最好使用回调模式并仅在初始装载时注册事件侦听器。如果您不使用回调模式()事件侦听器正在使用侦听器引用及其词法作用域,但在新呈现时会创建一个新函数,并使用更新的闭包,因此在处理程序中,您将无法访问更新的状态
const [userText, setUserText] = useState('');
const handleUserKeyPress = useCallback(event => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
const[userText,setUserText]=useState(“”);
const handleUserKeyPress=useCallback(事件=>{
const{key,keyCode}=事件;
如果(键代码===3
const [userText, setUserText] = useState('');
const handleUserKeyPress = useCallback(event => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
setUserText(prev => `${prev}${key}`);