djones_codeit
djones_codeit

Reputation: 13

Can't call setState on a component that is not yet mounted using Event Listeners

I'm getting this warning:

Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the Navbar component.

I created a Navbar component with a NavMin component that only renders when the screen has a width of 11000 or less. I think it has something to do with using componentDidMount and componentWillUnmount but I am not sure how to properly use it. I have tried using componentWillUnmount in NavMin but I receive this error:

Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

Here are the two components:

import  React, { Component } from 'react';
import { Link } from 'react-router-dom';
import bars from './Images/bars.png';
import './NavMini.css'

class NavMini  extends Component {

    componentWillUnmount(){

    }
    constructor(props){
    super(props)
        this.state = {
            showMenu: false 
        }

        this.showMenu = this.showMenu.bind(this)
        this.closeMenu = this.closeMenu.bind(this)
    }

  showMenu(event){
       event.preventDefault();

       this.setState({
           showMenu: true
       },
       () => {
           document.addEventListener('click', this.closeMenu);
       });
   }

   closeMenu(){
       this.setState({
           showMenu: false 
       }, () => {
           document.removeEventListener('click', this.closeMenu);
       })
   }

    render(){
        return(
            <div id="Navigation-mini"> 
            <button  onClick={this.showMenu} className="button-nav">
                 <img className="Mini-nav" src={bars} alt="nav-icon"/>
            </button>
            {
            this.state.showMenu
                ? (
                <div className="Navmenu">
                    <Link className="NavLink-mini" to='/'>Home</Link>
                    <Link className="NavLink-mini" to='/About'>About</Link>
                    <Link className="NavLink-mini" to='/Blog'>Blog</Link>
                    <Link className="NavLink-mini" to='/Contact'>Contact</Link>
                </div>
                )
                : (
                    null
                )
            }

         </div>
        )
    }
}

export default NavMini
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import Search from './Images/Search.png';
import Logo from './Images/Icon.png';
import NavMini from './NavMini'
import './NavBar.css';


class Navbar extends Component{
    constructor(props){
        super(props)

        let width = window.innerWidth;

        this.state = {
            show: false 
        }

        if(width < 1100){
            this.setState({
                show: true
            })
        }
    }

    render(){
    return (
        <div>
        <div id="Navigation">
            <div id="NavLogo">
                <Link to='/'><img id="CodeDestinee" src={Logo} alt="Logo" /></Link>
                    <h3 id="LogoName">Code <br/> Destinee</h3>
            </div>

            <div id="Navbar">
                <Link className="NavLink" to='/'>Home</Link>
                <Link className="NavLink" to='/About'>About</Link>
                <Link className="NavLink" to='/Blog'>Blog</Link>
                <Link className="NavLink" to='/Contact'>Contact</Link>
                <img className="NavLink" id="SearchIcon" src={Search} alt="Search-Icon" />
            </div>
        </div>

        { !this.state.show ? <NavMini /> : null } 
        </div>
    )
    }
}

export default Navbar

Can someone help me understand what I am doing wrong?

Upvotes: 1

Views: 642

Answers (3)

Julia
Julia

Reputation: 704

componentDidMount() {
  let width = window.innerWidth;
  if(width < 1100){
      this.setState({
          show: true
      })
  }
}

Constructor is the only place where you should assign this.state directly. In all other methods, you need to use this.setState() instead.

Upvotes: 0

jas7457
jas7457

Reputation: 1782

As pointed out above, you're calling setState in the constructor which you shouldn't be doing. The above solution may work, but I believe a better solution is to set show to true or false in one expression, depending on the width:

this.state = {
    show: width < 1100 
}

This will set this.state.show to true or false, depending on the width.

Upvotes: 0

Subin Sebastian
Subin Sebastian

Reputation: 10997

You are using this.setState in constructor, please change it to

if(width < 1100){
    this.state  = {
        show: true
    }
}

Upvotes: 2

Related Questions