Home > Software engineering >  Console.log is telling me my div is null when I try and add a class to it
Console.log is telling me my div is null when I try and add a class to it

Time:09-08

I'm adding a keydown eventlistener that'll simply make my box div show. However, when I press a key, nothing happens and instead the console tells me, "Uncaught TypeError: box is null". No idea what the problem is, please help

Here's my App.js:

import "./styles.css"

const box = document.querySelector(".box");
const notification = document.querySelector(".notif");

window.onload = document.addEventListener("keydown", e => {
  box.classList.add("active");
  notification.classList.add("inactive");
})

function App() {

  return (
    <>
        <div className='notif'>Press Any Key</div>
        <div className='box'>
          <h2>20</h2>
          <h1>Shift</h1>
        </div>
    </>
  );
}

export default App;

and the css: @import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');

:root {
    --teal: #00ccff;
    --pink: #d400d4;
}

*, *::before, *::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: 'Poppins', sans-serif;
}

body {
    display: flex;
    min-height: 100vh;
    align-items: center;
    justify-content: center;
    background: #0e1538;
}

.box {
    position: relative;
    width: 300px;
    height: 300px;
    display: flex;
    justify-content: center;
    align-items: center;
    background: rgba(0,0,0,.5);
    overflow: hidden;
    border-radius: 20px;
    flex-direction: column;
    display: none;
}

.box.active {
    display: flex;
}

.box::before {
    content: '';
    position: absolute;
    width: 150px;
    height: 140%;
    background: linear-gradient(var(--teal), var(--pink));
    animation: animate 4s linear infinite;
}

@keyframes animate {
    0%{
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(360deg);
    }
}

.box::after {
    content: '';
    position: absolute;
    background: #0e1538;
    inset: 4px;
    border-radius: 16px;
}

.box h2 {
    position: relative;
    color: white;
    font-size: 5em;
    z-index: 10;
}

.box h1 {
    position: relative;
    color: white;
    z-index: 10;
    background: rgba(0,0,0,.5);
    width: 97.5%;
    text-align: center;
    letter-spacing: 5px;
}

.notif {
    font-size: 3em;
    background: var(--teal);
    padding: 0 20px;
    border-radius: 20px;
}

.notif.inactive {
    display: none;
}

CodePudding user response:

import "./styles.css"
import {useEffect} from 'react'



function App() {
  useEffect(()=>{
    const box = document.querySelector(".box");
    const notification = document.querySelector(".notif");
    document.addEventListener("keydown", e => {
        box.classList.add("active");
        notification.classList.add("inactive");
    })
  },[])
  return (
    <>
        <div className='notif'>Press Any Key</div>
        <div className='box'>
          <h2>20</h2>
          <h1>Shift</h1>
        </div>
    </>
  );
}

export default App;

CodePudding user response:

You should be maintaining/updating state with the new class information when you press a key. Add the listener within the useEffect (along with a cleanup function). When a key is pressed the listener calls a function that updates the state (in this case switching the active/inactive classes). The component is re-rendered, and the elements' class names are changed using a little helper function.

const { useEffect, useState } = React;

function Example() {

  // Initialise state
  const [ active, setActive ] = useState({
    box: false,
    notification: true
  });

  // A function to update the state
  function toggleActive() {
    setActive(prev => ({
      box: !prev.box,
      notification: !prev.notification
    }));
  }
 
  // An effect that adds a listener, w/ a cleanup function
  useEffect(() => {
    window.addEventListener('keydown', toggleActive);
    return () => {
      window.removeEventListener('keydown', toggleActive);
    }
  }, []);

  // Returns the active status of the element from state
  function isActive(type) {
    return active[type] ? 'active' : 'inactive';
  }

  return (
    <div>
      <div className={isActive('notification')}>
        Press Any Key
      </div>
      <div className={isActive('box')}>
        <h2>20</h2>
        <h1>Shift</h1>
      </div>
    </div>
  );

}

ReactDOM.render(
  <Example />,
  document.getElementById('react')
);
.active { color: red; }
.inactive { color: black; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

  • Related