如何使用 useEffect 钩子注册事件? [英] How to register event with useEffect hooks?

查看:32
本文介绍了如何使用 useEffect 钩子注册事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习关于如何使用钩子注册事件的 Udemy 课程,讲师给出了以下代码:

 const [userText, setUserText] = useState('');const handleUserKeyPress = 事件 =>{const { key, keyCode } = 事件;if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {setUserText(`${userText}${key}`);}};useEffect(() => {window.addEventListener('keydown', handleUserKeyPress);返回 () =>{window.removeEventListener('keydown', handleUserKeyPress);};});返回 (<div><h1>随意打字!</h1><blockquote>{userText}</blockquote>

);

现在效果很好,但我不相信这是正确的方法.原因是,如果我理解正确,在每次重新渲染时,事件都会不断注册和注销,我只是认为这不是正确的方法.

所以我对下面的 useEffect 钩子做了一点修改

useEffect(() => {window.addEventListener('keydown', handleUserKeyPress);返回 () =>{window.removeEventListener('keydown', handleUserKeyPress);};}, []);

通过将一个空数组作为第二个参数,让组件只运行一次效果,模仿 componentDidMount.当我尝试结果时,奇怪的是在我输入的每个键上,它不是附加,而是被覆盖.

我期待 setUserText(${userText}${key}); 将新键入的键附加到当前状态并设置为新状态,但相反,它是忘记旧状态并用新状态重写.

我们应该在每次重新渲染时注册和取消注册事件真的是正确的方法吗?

解决方案

处理此类情况的最佳方法是查看您在事件处理程序中执行的操作.

如果您只是使用之前的 state 设置 state,最好使用回调模式并仅在 initial 挂载时注册事件侦听器.

如果您不使用 回调模式,则侦听器参考事件侦听器正在使用它的词法范围,但会在每次渲染时创建一个具有更新闭包的新函数;因此在处理程序中您将无法访问更新的状态

const [userText, setUserText] = useState("");const handleUserKeyPress = useCallback(event => {const { key, keyCode } = 事件;if(keyCode === 32 || (keyCode >= 65 && keyCode <= 90)){setUserText(prevUserText => `${prevUserText}${key}`);}}, []);useEffect(() => {window.addEventListener(keydown", handleUserKeyPress);返回 () =>{window.removeEventListener(keydown", handleUserKeyPress);};}, [handleUserKeyPress]);返回 (<div><h1>随意打字!</h1><blockquote>{userText}</blockquote>

);

I am following a Udemy course on how to register events with hooks, the instructor gave the below code:

  const [userText, setUserText] = useState('');

  const handleUserKeyPress = event => {
    const { key, keyCode } = event;

    if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
      setUserText(`${userText}${key}`);
    }
  };

  useEffect(() => {
    window.addEventListener('keydown', handleUserKeyPress);

    return () => {
      window.removeEventListener('keydown', handleUserKeyPress);
    };
  });

  return (
    <div>
      <h1>Feel free to type!</h1>
      <blockquote>{userText}</blockquote>
    </div>
  );

Now it works great but I'm not convinced that this is the right way. The reason is, if I understand correctly, on each and every re-render, events will keep registering and deregistering every time and I simply don't think it is the right way to go about it.

So I made a slight modification to the useEffect hooks to below

useEffect(() => {
  window.addEventListener('keydown', handleUserKeyPress);

  return () => {
    window.removeEventListener('keydown', handleUserKeyPress);
  };
}, []);

By having an empty array as the second argument, letting the component to only run the effect once, imitating componentDidMount. And when I try out the result, it's weird that on every key I type, instead of appending, it's overwritten instead.

I was expecting setUserText(${userText}${key}); to have new typed key append to current state and set as a new state but instead, it's forgetting the old state and rewriting with the new state.

Was it really the correct way that we should register and deregister event on every re-render?

解决方案

The best way to go about such scenarios is to see what you are doing in the event handler.

If you are simply setting state using previous state, it's best to use the callback pattern and register the event listeners only on initial mount.

If you do not use the callback pattern, the listeners reference along with its lexical scope is being used by the event listener but a new function is created with updated closure on each render; hence in the handler you will not be able to access the updated state

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>
  );

这篇关于如何使用 useEffect 钩子注册事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆