Grambam
Grambam

Reputation: 554

Components mounting many times

So I'm simply trying to toggle the visibility of a React component on a specific keypress.

This is working perfectly, but it seems every Time i toggle the component visibility using ctrl+`, the process gets slower and slower, and my console.log(e) from the onKey function in my app component gets called 10,50,100, 1000 times etc.

This is what I have so far


ReactDOM.render(
  <React.StrictMode>
    <Router>
      <App />
    </Router>

  </React.StrictMode>,
  document.getElementById('root')
);

function App() {
  const [compHidden, toggleComp] = useState(true);

  const onKey = (e) => {
    console.log(e)
    if(e.ctrlKey && e.key === '`') {
      toggleComp(!compHidden);
    }
  }

  document.addEventListener('keydown', onKey);

  return (
      <ComponentToHide hidden={compHidden}/>
  );
}

function ComponentToHide(props) {

  return (
    <div style={{display: props.hidden ? 'none' : 'flex'}}>
     <p>Visible</p>
    </div>
  )
}

Upvotes: 2

Views: 149

Answers (1)

Josh Hunt
Josh Hunt

Reputation: 14511

Do not use document.addEventListener inside the render function, as that function is called every time your component renders and it will add a new event listner each time.

Instead, use the React Hook React.useEffect() to add the event listner only once as the component is mounted:

function App() {
  const [compHidden, setCompHidden] = useState(true);

  useEffect(() => {
    const onKey = (e) => {
      console.log(e)
      if(e.ctrlKey && e.key === '`') {
        setCompHidden(value => !value);
      }
    }

    document.addEventListener('keydown', onKey);

    return () => document.removeEventListener('keydown', onKey);
  }, [])

  return (
      <ComponentToHide hidden={compHidden}/>
  );
}

Two things to note:

  1. useEffect's second argument, just an empty array, tells React only to run that function once at the beginning of the components lifecycle
  2. You can return a cleanup function that is ran as your component is unmounted. We use this here to remove the event listener to fix an additional memory leak.

Upvotes: 3

Related Questions