0

I'm trying to make a simple animation when the burger element is clicked

I'm trying to update the following state with an animation when the burger is clicked but the state doesn't update no matter what i try.

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



const Navbar = () => {

  const [animations, setAnimations] = useState({
      style1:{animation:null},
      style2:{animation:null},
      style3:{animation:null},
      style4:{animation:null}
  }) 


  let burger = useRef(null)
  let nav = useRef(null)
  function HandleBurger(){
        nav.classList.toggle('nav-active');
        Object.keys(animations).forEach((link, index) => {
            if (animations[link].animation) {
              setAnimations(prevState =>{
                return  {...prevState,  animation: ''}
              });
            } else {

                  setAnimations(prevState =>{
                    return  {link: {animation: `navLinkFade 0.5s ease forwards ${index / 7 + 1}s`}}
                  });
                  console.log(animations);
            }            
          })          
          burger.classList.toggle('toggle') 
 }
  
  return (
        <nav className="navbar">
            <div className="logo">
                <h3 id="art">BURJTECH</h3>
                <h3 id="scope">LIMITED</h3>
            </div>
            <div className="side-header" ref={el=>nav=el}>
                <li style={animations["style1"]}><a className="cool-link" href="/">Homepage</a></li>
                <li style={animations["style2"]}><a className="cool-link" href="/about">About</a></li>
                <li style={animations["style3"]}><a className="cool-link" href="/services">Services</a></li>
                <li style={animations["style4"]}><a className="cool-link" href="/contact">Contact</a></li>
            </div>
            <div className="burger" ref={el=>burger=el} onClick={HandleBurger}>
                <div className="line1"></div>
                <div className="line2"></div>
                <div className="line3"></div>
            </div>
        </nav>
  )
}

Edit: Someone suggested i post the full code

  • You shouldn't set state in a loop. But aside from that, how do you know your state doesn't update? – Adam Jenkins May 22 '21 at 01:08
  • This seems to be a very complicated way of handling css animations. You can probably accomplish the same thing by toggling the class name of an element, then apply the animations accordingly from an external css file. – iismaell May 22 '21 at 01:13
  • @Adam I ran a console.log to check, and the values remain null at every loop – Preshy Jones May 22 '21 at 01:14
  • setState is asynchronous. So, you state is being updated but because you have console.log right after the setState it doesn't show up in the logs. Move the setState in a useEffect with your state values as its array dependencies, you'll be able to see the state changes in console logs. – Tom Bombadil May 22 '21 at 01:24
  • @PreshyJones aside from what the other commentor said, which is correct, you're not doing things in a very react-y way here (when you are doing react in an un-react-y way, it makes react seem very hard), take a look at this: https://stackoverflow.com/questions/30782948/why-calling-react-setstate-method-doesnt-mutate-the-state-immediately – Adam Jenkins May 22 '21 at 01:24
  • @adam It was orignally done in vanilla Javascript, i'm redoing the entire website in React – Preshy Jones May 22 '21 at 01:40

1 Answers1

1

There's a lot of bad smells going on in your code. The first improvement that can be made is for you to use a single setState call instead of calling it in a loop:

function HandleBurger() {
 //...

 setAnimations(state => {
    return Object.keys(state).reduce((acc,key,index) => {
      if(state[key].animation) return {...acc,[key]:animation:null};
      return {...acc,[key]:animation: `navLinkFade ....`}
    },state);
 });

 //...
}

You also should not being using refs to toggle class names, that's not the react way of doing things. I'd really like to see the rest of you component.

Post it.

Adam Jenkins
  • 51,445
  • 11
  • 72
  • 100