首页 > 解决方案 > reactjs中的事件监听器和闭包

问题描述

尽管添加了removeEvent ,但customFunction的控制台日志在每次渲染时都会打印多次。我知道这与关闭有关,但无法确定解决方案。任何帮助表示赞赏。

import React, { useEffect, useState } from "react";

function addOnEvent(event_name, callback){
    document.addEventListener(event_name, (e)=>callback(e.detail));
}
function removeEvent(event_name, callback){
    document.removeEventListener(event_name, callback);
}
function App() {
  const [some_state, set_some_state] = useState([]);
    const customFunction = (e) => {
        //some action here setting some_state
        console.log("Console prints multiple times")
    };
  useEffect(() => {
    addOnEvent('custom_event', customFunction)
    return () => {
      removeEvent('custom_event', customFunction)
    };
  }, [some_state]);
  
  return (
    <div className="App">
    </div>
  );
}

export default App;

标签: javascriptreactjsaddeventlistener

解决方案


您没有正确清理事件侦听器。这是因为您使用新的箭头函数包装了给定的回调。因此,removeEventListener将找不到要删除的事件侦听器。

e.detail您可以通过删除箭头功能并在您的中提取来解决此问题customFunction

import React, { useEffect, useState } from "react";

function addOnEvent(event_name, callback){
    document.addEventListener(event_name, callback);
}
function removeEvent(event_name, callback){
    document.removeEventListener(event_name, callback);
}
function App() {
  const [some_state, set_some_state] = useState([]);
    const customFunction = (e) => {
        //some action here setting some_state
        console.log("Console prints multiple times")
    };
  useEffect(() => {
    addOnEvent('custom_event', customFunction)
    return () => {
      removeEvent('custom_event', customFunction)
    };
  }, [some_state]);
  
  return (
    <div className="App">
    </div>
  );
}

export default App;

如果您真的只想要e.detail回调中的 ,您还可以更新该addOnEvent函数以返回一个未侦听的函数,如下所示:

import React, { useEffect, useState } from 'react';

function addOnEvent(event_name, callback) {
  const listener = e => callback(e.detail);
  document.addEventListener(event_name, listener);
  return () => document.removeEventListener(event_name, listener);
}

function App() {
  const [some_state, set_some_state] = useState([]);
  const customFunction = (e) => {
    //some action here setting some_state
    console.log('Console prints multiple times');
  };
  useEffect(() => {
    const unlisten = addOnEvent('custom_event', customFunction);
    return () => unlisten();
  }, [some_state]);

  return (
    <div className="App">
    </div>
  );
}

export default App;

推荐阅读