React – will not re render on state change

All we need is an easy explanation of the problem, so here it is.

I’m all new to react.
Why does my page not re render on mouse over and mouse out when my state changes? If I look at console.log, I can see the state changes. But I can’t get this to work. Here is my code:

export default class Nav extends React.PureComponent {

  constructor(props) {
    super(props);
    this.navLevelOneId = '';

    this.state = {
      showSubMenu: []
    };
  }

  // Mouse over function
  handleHover = (id,event) => {
    let showSubMenu=this.state.showSubMenu;
    showSubMenu[id]=!showSubMenu[id]
    this.setState({showSubMenu: showSubMenu}, () => {
      console.log(this.state.showSubMenu);  
    });
  }

  render() {

    return (

          <div ref="megaMenu" className="navbar navbar-default navbar-static-top">
            <div className="container">
              <div className="navbar-header">
                <button type="button" className="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                  <span className="icon-bar"></span>
                  <span className="icon-bar"></span>
                  <span className="icon-bar"></span>
                </button>
              </div>
              <div className="navbar-collapse collapse">
                      <ul className="nav navbar-nav">
                        <li onMouseOver={this.handleHover.bind(this,0)} onMouseOut={this.handleHover.bind(this,0)}>
                                  <a>Home</a>
                                </li>
                        <li className="dropdown menu-large" onMouseOver={this.handleHover.bind(this,1)} onMouseOut={this.handleHover.bind(this,1)}>
                    <a className="dropdown-toggle" data-toggle="dropdown">Product Listing</a>

                                    <ul className={"dropdown-menu megamenu row " + this.state.showSubMenu[1]}>
                      <li>
                        <div className="col-sm-6 col-md-3">
                          <a href="" className=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"thumbnail">
                                  <img src="https://placehold.it/150x120" alt="test" />
                          </a>
                        </div>
                        <div className="col-sm-6 col-md-3">
                              <a href="" className=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"thumbnail">
                                  <img src="https://placehold.it/150x120" alt="test" />
                          </a>
                        </div>
                        <div className="col-sm-6 col-md-3">
                              <a href="" className=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"thumbnail">
                                  <img src="https://placehold.it/150x120" alt="test" />
                          </a>
                        </div>
                        <div className="col-sm-6 col-md-3">
                          <a href="" className=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"thumbnail">
                                  <img src="https://placehold.it/150x120" alt="test" />
                          </a>
                          </div>
                              </li>
                    </ul>

                  </li>

                        <li className="dropdown menu-large" onMouseOver={this.handleHover.bind(this,2)} onMouseOut={this.handleHover.bind(this,2)}>
                            <a className="dropdown-toggle" data-toggle="dropdown">Categories</a>

                                    <ul className={"dropdown-menu megamenu row " + this.state.showSubMenu[2]}>
                      <li>
                        <div className="col-sm-6 col-md-3">
                          <a href="" className=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"thumbnail">
                                  <img src="https://placehold.it/150x120" alt="test" />
                          </a>
                        </div>
                        <div className="col-sm-6 col-md-3">
                              <a href="" className=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"thumbnail">
                                  <img src="https://placehold.it/150x120" alt="test" />
                          </a>
                        </div>
                        <div className="col-sm-6 col-md-3">
                              <a href="" className=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"thumbnail">
                                  <img src="https://placehold.it/150x120" alt="test" />
                          </a>
                        </div>
                        <div className="col-sm-6 col-md-3">
                          <a href="" className=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"thumbnail">
                                  <img src="https://placehold.it/150x120" alt="test" />
                          </a>
                          </div>
                              </li>
                    </ul>

                        </li>
                  </ul>
                  </div>
            </div>
          </div>


            );

      }

    }

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Check out the difference between using Component and PureComponent.

Briefly, PureComponent performs a shallow comparison on state change. That means that it compares only references for state objects and arrays (in your case this.state.showSubMenu is an array and it’s reference doesn’t change so React won’t force a rerender there)

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply