簡體   English   中英

了解反應功能組件中的點擊事件和內存

[英]Understanding click events and memory in react function components

我一直在使用函數組件和鈎子,現在我正在嘗試更深入地研究事件以及它們如何保存在內存中。 我一直在使用 chrome 開發工具性能選項卡來監控行為。 有幾件事我不清楚,也許有人可以為我澄清。

所以我做了3個不同的設置。 第一個顯示事件明顯內存泄漏的事件在每次渲染時添加了多次。 這最終會導致渲染崩潰或無限循環。 或者至少那是看起來正在發生的事情。

const App = () => {
  const [count, setCount] = React.useState(0);
  const onKeyDown = () => setCount(count => count + 1);


  document.addEventListener('keydown', onKeyDown); 

    return (
    <div className='wrapper'>
      <div>Click any key to update counter</div>
      <div className='counter'>{count}</div>
    </div>
    );
};

ReactDOM.render(<App />, document.querySelector("#app"))

這表明每個偵聽器的額外事件調用明顯增加。 查看事件日志,然后增加已添加的事件階梯。

在此處輸入圖片說明

接下來

const App = () => {
  const [count, setCount] = React.useState(0);
  const onKeyDown = () => setCount(count => count + 1);


 React.useEffect(() => {
   document.addEventListener('keydown', onKeyDown);
   return () => document.removeEventListener('keydown', onKeyDown);
  }, [] ); 

    return (
    <div className='wrapper'>
      <div>Click any key to update counter</div>
      <div className='counter'>{count}</div>
    </div>
    );
};

ReactDOM.render(<App />, document.querySelector("#app"))

結果更好,因為聽眾一次只有一個電話。 但我注意到聽眾人數仍在飆升。 添加它們時的峰值並不那么尖銳。 但是聽眾的人數是千人。 所有這些聽眾在哪里被添加。 jsfiddle 是否添加了偵聽器。 最好將這個測試隔離在 jsfiddle 之外的一個 html 頁面中。

在此處輸入圖片說明

然后我讀到了使用鈎子 useCallback 來記住函數並返回函數的兌現版本。 所以我嘗試了這個。

const App = () => {
  const [count, setCount] = React.useState(0);

    const cb = React.useCallback(() => {
      console.log('cb');
      setCount(count => count + 1);
    }, [] );

    return (
    <div className='wrapper'>
      <div onClick={cb}>Click any key to update counter</div>
      <div className='counter'>{count}</div>
    </div>
    );
};

ReactDOM.render(<App />, document.querySelector("#app"))

但結果證明這與上次使用 useEffect 的測試類似。 仍然有大量的聽眾,但沒有像第一次測試那樣崩潰。
那么這里的交易是什么我錯過了使用 useCallback 鈎子進行記憶的一些東西。 偵聽器看起來像是被瘋狂添加而沒有被垃圾收集。

我將在沒有 jsfiddle 的情況下隔離此測試,但只是想發布到社區以首先對此有所了解。

你不要在 React 中使用 addEventListener !

相反,你會做這樣的事情:

const App = () => {
  let count = 0;
  const onAddHandler = () => {    
    count++;
    console.log(count);
    this._count.innerText = count;   
 }
 return (
    <div className='wrapper'>
       <div onClick={()=>onAddHandler()}>Click any key to update counter</div>
       <div className='counter' ref={(el) => this._count = el}></div>
       </div>
  );
}

另外,不確定您為什么使用 React.useState。 功能組件的全部意義在於它們是無狀態的。 我不喜歡在功能組件中使用這個新的 useState 鈎子。

您可能正在尋找使用鈎子的示例是:

import React, { useState, useEffect } from 'react';
import {render} from 'react-dom';

function Example() {
   const [count, setCount] = useState(0);

   useEffect(() => {
     document.title = `You clicked ${count} times`;
   });
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
   </div>
 );
}

render(<Example />, document.getElementById('root'));

React 文檔https://reactjs.org/docs/hooks-effect.html

如果您熟悉 React 類的生命周期方法,您可以將 useEffect Hook 視為 componentDidMount、componentDidUpdate 和 componentWillUnmount 的組合。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM