1

I am trying to make an animated burger menu with an event listener that mounts on load. The event listener works but the transition between the two stylings I toggle between does not work. Code below. I'm sure that my method of toggling between preset styles is wrong, whether or not it's part of the problem. Thanks.

import ReactDOM from 'react-dom'
import '../style/Main.css'
import styled from "styled-components"

const originalBurger = styled.div`
    display: inline;
    div {
        background-color: #fcfcfc;
        height: 4px;
        width: 42px;
        margin: 10px;
        transition: all 0.3s ease forwards;
    }
`;

const animatedBurger = styled.div`
    display: inline;
    div {
        background-color: #000000;
        height: 4px;
        width: 42px;
        margin: 10px;
        transition: all 0.3s ease forwards;
        &:nth-child(1) {
            transform: rotate(45deg)
        }
        &:nth-child(2) {
            opacity: 0;
        }
        &:nth-child(3) {
            transform: rotate(315deg);
        }
    }
`;

let StyledBurger = originalBurger;

class Burger extends Component {
    componentDidMount() {
        ReactDOM.findDOMNode(this).addEventListener("click", () => {
            if (StyledBurger === animatedBurger) {
                StyledBurger = originalBurger;
                this.forceUpdate();
            } else if (StyledBurger === originalBurger) {
                StyledBurger = animatedBurger;
                this.forceUpdate();
            }
            this.componentDidMount();
        })
    }

    componentWillUnmount() {
        ReactDOM.findDOMNode(this).removeEventListener();
    }

    render() {
        return (
            <StyledBurger>
                <div />
                <div />
                <div />
            </StyledBurger>
        )
    }
}

export default Burger

UPDATE

used the help of the approved answer and ended with this

import ReactDOM from 'react-dom'
import '../style/Main.css'
import styled from "styled-components"

const getActiveStyle = (props) =>  `
    &:nth-child(1) {
        transform: rotate(-45deg) translate(-10px, 12px)
    }
    &:nth-child(2) {
        opacity: 0;
    }
    &:nth-child(3) {
        transform: rotate(45deg) translate(-10px, -12px);
    }
`
const originalBurger = styled.div`
    display: inline;
    div {
        background-color: #fcfcfc;
        height: 6px;
        width: 50px;
        margin: 10px;
        transition: all 0.3s ease;
        ${(props) => props.isActive ? getActiveStyle(props) : ""}
    }
`;

let StyledBurger = originalBurger;

class Burger extends Component {
    constructor(){
        super();
        this.state = {
            isActive: false
        }
    }
    render() {
        return (
            <StyledBurger isActive={this.state.isActive} onClick={()=> this.setState({isActive: !this.state.isActive})}>
                <div />
                <div />
                <div />
            </StyledBurger>
        )
    }
}
export default Burger;
2
  • you might separate the style of the ham burger menu into a CSS file and create a state to change the style on click event instead of forceUpdate() Commented Sep 5, 2020 at 3:44
  • Why addEventListener? Why not put an onClick prop on the component? Commented Sep 5, 2020 at 5:56

1 Answer 1

1

There are much better and simpler way to achieve it. In your style component you can have a props for active/inactive state. It is documented here: https://styled-components.com/docs/basics#passed-props The code can look likes this:

import ReactDOM from 'react-dom'
import '../style/Main.css'
import styled from "styled-components"

const getActiveStyle = (props) =>  `
    &:nth-child(1) {
        transform: rotate(45deg)
    }
    &:nth-child(2) {
        opacity: 0;
    }
    &:nth-child(3) {
        transform: rotate(315deg);
    }
`
const originalBurger = styled.div`
    display: inline;
    div {
        background-color: props.isActive ? #000000 : #fcfcfc;
        height: 4px;
        width: 42px;
        margin: 10px;
        transition: all 0.3s ease forwards;
        ${(props) => props.isActive ? getActiveStyle(props) : ""}
    }
`;

let StyledBurger = originalBurger;

class Burger extends Component {
    constructor(){
        this.state = {
            isActive: false
        }
    }
    render() {
        return (
            <StyledBurger isActive={this.state.isActive} onClick={()=> this.setState({isActive: !this.state.isActive})}>
                <div />
                <div />
                <div />
            </StyledBurger>
        )
    }
}
export default Burger;
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.