【问题标题】:What is the right way to manage synthetic events using hooks and update the state from event handlers?使用钩子管理合成事件并从事件处理程序更新状态的正确方法是什么?
【发布时间】:2019-09-14 05:45:49
【问题描述】:

新手在这里做出反应,使用钩子管理合成事件的状态并从事件处理程序更新状态的正确方法是什么,我浏览了官方的反应文档,找不到具体信息。

这是我迄今为止尝试过的。

第 1 步:声明用于更新状态的钩子变量

const [state, setState] = React.useState(0);

第 2 步:声明处理合成事件和更新状态的函数

const handleCopy = (e) => {
   setState(state+1);
   e.preventDefault();
};

第 3 步:添加事件侦听器并将事件传递给函数

document.addEventListener('copy', (e) => handleCopy(e));

第 4 步:将状态传递给组件

<Component value={state}/>

我在这里遇到的问题很少

  1. 状态更新未反映在组件中。但它似乎确实在更新状态,因为 console.log 似乎正确地反映了状态。
  2. 随着时间的推移,注册的事件侦听器过多。

为了防止太多的事件侦听器,我将 addEventListener 包装为只注册一次的条件

const [syntheticEventRegistered, setSyntheticEventRegistered] = React.useState(false);

if(!syntheticEventRegistered)
{
    document.addEventListener('copy', (e) => handleCopy(e));
    setSyntheticEventRegistered(true);
}

这确实解决了太多的事件侦听器,但 handleCopy 函数现在只反映默认状态。即 state = 0 而不是最新状态,也不会更新组件值。

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    建议在 componentDidMount 生命周期中注册一个事件监听器。您可以在功能组件中使用 useEffect 挂钩。使用 useEffect 您可以订阅和取消订阅事件(在返回函数中)。这样您就可以防止多次注册。我创建了一个示例。

    import React, { useState, useEffect } from "react";
    import ReactDOM from "react-dom";
    
    import "./styles.css";
    const MyFunctionalComponent = () => {
      let [state, setState] = useState(0);
    
      useEffect(() => {
        const handleCopy = e => {
          setState(state + 1);
          e.preventDefault();
        };
    
        document.addEventListener("copy", handleCopy);
        // Specify how to clean up after this effect:
        return () => {
          document.removeEventListener("copy", handleCopy);
        };
      }, [state]);
    
      return <div>{state}</div>;
    };
    
    function App() {
      return (
        <div className="App">
          <MyFunctionalComponent />
          <h2>Start editing to see some magic happen!</h2>
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    

    您可以在这里查看:https://codesandbox.io/s/little-rgb-dfre7

    它对我有用。如果您从右侧选择某些内容并按 ctrl+c,则计数器会增加。

    【讨论】:

    • 感谢您的意见。我删除了“return function () =>”中的函数,它几乎可以按预期更新状态,但不会使用新状态重新渲染组件。
    • 我还没有关注你的渲染部分。尝试一些简单的事情,例如 &lt;div&gt;{state}&lt;/div&gt; 它应该可以工作。
    • 更新状态后即使是简单的div也没有更新
    • 我还是不知道你的代码有什么问题。也许您使用组件,您应该从中扩展一个新组件。无论如何,我用一个工作示例更新了我的答案。
    • 我的错,这是我正在使用的组件的道具有问题,感谢您的帮助,接受这个作为答案。
    猜你喜欢
    • 2021-09-12
    • 2016-02-03
    • 2019-07-26
    • 2019-08-11
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多