harry
harry

Reputation: 501

In react js this.state getting state of null in function

I want to change backgroundColor on hover but getting error when onMouseOver function get call it says "Uncaught TypeError: Cannot read property 'setState' of null" in console. Please let me know what is wrong with this code thanks.

import React from 'react'
import { Link } from 'react-router'
import { prefixLink } from 'gatsby-helpers'
import Helmet from 'react-helmet'
import { config } from 'config'

export default class Index extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
       header: "harry header",
       content: "content for harry",
       activeClass : 'normal',
       hovered :false
      }
   }
   componentDidMount(){
      var cssClass = 'normal';
      window.addEventListener('scroll', (event) => {
         if(event.srcElement.body.scrollTop == 0){
             cssClass = 'normal';
         }else{
             cssClass = 'fixed';
         }
         this.setState({
            activeClass: cssClass,
         })
      });
  }
  style() {
      if (this.state.hovered) {
        return { backgroundColor: "red" }
      } else {
        return { backgroundColor: "grey" }
      }
  }
  onMouseOver (){
      this.setState({ hovered:true });
  }
  onMouseOut (){
      this.setState({ hovered:false });
  }
  render() {
    return (
      <div>
        <header className={`header ${this.state.activeClass}`} >
          <div className="top-bar">
            <span><a href="tel:6788272782">678-827-2782 </a></span>
            <span><a href="mailto:[email protected]"> [email protected]</a></span>
            <button>Login</button>
          </div>
        </header>
        <div className="banner-main-outer">
          <div className="banner-main">
          </div>
          <div className="abs-height-caption">
            <div className="caption-banner">
              <div className="logo-main"><img src={require('../img/knotel.svg')}/></div>
              <h2>Commit to your business, not a lease</h2>
              <span>Headquarters as a Service</span>
              <button>Book a tour</button>
            </div>
            <ul className="kno-ul">
              <li><a>   LOCATIONS</a></li>
              <li><a>   SPACES</a></li>
              <li><a>   Services</a></li>
              <li><a>   Events</a></li>
              <li className="kno-hiring"><a>    We're hiring</a></li>
            </ul>
          </div>
          <div className="banner-btm-link">
            <a>Tenant Reps</a>
            <a>I have space</a>
          </div>
        </div>
        <div className="Spaces-Offer">
          <div className="header-bar">Our Locations</div>
          <div className="map-outer">
            <img src={require('../img/map.jpg')} />
          </div>
        </div>
        <div className="our-offer">
          <div className="header-bar">Spaces We Offer</div>
          <div onMouseOver={this.onMouseOver} 
                   onMouseOut={this.onMouseOut} 
                   style={this.style()} className="offer-cards">
            <ul>
              <li className="blue-block">
                <h1>Flexible Workspace For Growing Teams</h1>
                <p>We provide the resources so growing teams can focus their business. Many of our companies have graduated from coworking spaces.</p>
                <div className="offer-res-img" />
              </li>
              <li className="brown-block">
                <h1>Branded Floors for Established Companies</h1>
                <p>When you need your own floor we provide dedicated, branded space for your company with a backbone of Knotel management.</p>
                <div className="offer-res-img" />
              </li>
              <li className="purple-block">
                <h1>Flagship Buildings for World Leaders</h1>
                <p>When you are ready to take over the world, Knotel will take over a building for you. Turnkey commercial real estate at any size.</p>
                <div className="offer-res-img" />
              </li>
            </ul>
          </div>
        </div>
        <div className="our-services">
          <div className="header-bar">Services We Provide</div>
          <div className="sources-cards">
            <ul>
              <li className="active">
                <h1>Sourcing and Buildout</h1>
                <p>Knotel bundles property market insight with interior design expertise and buildout management, which ensures the client’s space vision is met on time, on budget, and without headaches.</p>
                <div className="sources-res-img" />
              </li>
              <li>
                <h1>Seamless Operations</h1>
                <p>Knotel provides comprehensive office services powered by domain experts and best of breed technology. Enjoy the highest ratio of conference rooms per person in the industry, and exclusive deals at a high quality set of partners</p>
                <div className="sources-res-img" />
              </li>
              <li>
                <h1>Flexible Terms</h1>
                <p>Knotel has a simple pricing structure with flexible terms. We offer various month to month and fixed term agreements tailored to your needs.</p>
                <div className="sources-res-img" />
              </li>
              <li>
                <h1>Events and Community</h1>
                <p>Knotels are vibrant spaces, with engaged communities and a strong roster of events. Enjoy office hours and informal access to like-minded industry professionals.</p>
                <div className="sources-res-img" />
              </li>
            </ul>
            <div className="source-img-change" />
          </div>
        </div>
        <div className="our-events">
          <div className="header-bar">Events we're hosting</div>
          <div className="form-contact">
            <div className="main-outer-inp">
              <h1>Stay in the know about Knotel events and news</h1>
              <div className="input-blocks">
                <input placeholder="First Name (required)" type="text" />
              </div>
              <div className="input-blocks">
                <input placeholder="Last Name (required)" type="text" />
              </div>
              <div className="input-blocks">
                <input placeholder="Email (required)" type="text" />
              </div>
            </div>
            <div className="sub-btn">
              <button>SUBSCRIBE</button>
            </div>
          </div>
        </div>
        <div className="structure-events">
          <div className="structure-container">
            <div className="events-details">
              <div className="events-knotels">COMING EVENTS</div>
              <ul>
                <li>
                  <div className="img-block"><img src={require('../img/manhattan-logo.jpg')} /></div>
                  <div className="eventdetail">
                    <div className="dates-on">
                      <span>07</span>
                      <p>Jun</p>
                    </div>
                    <div className="gtm-para">
                      <span>Entrepreneurship Council</span>
                      <p>8:30 am to 10:00 am at Knotel </p>
                    </div>
                  </div>
                </li>
                <li>
                  <div className="img-block"><img src={require('../img/Parrot Memento Knotel.png')} /></div>
                  <div className="eventdetail">
                    <div className="dates-on">
                      <span>14</span>
                      <p>Feb</p>
                    </div>
                    <div className="gtm-para">
                      <span>Knotel Private Founders Series</span>
                      <p>5:00 pm to 7:00 pm at Knotel Union Sq 1</p>
                    </div>
                  </div>
                </li>
              </ul>
            </div>
            <div className="events-details">
              <div className="events-knotels">PAST EVENTS</div>
              <ul>
                <li>
                  <div className="img-block"><img src={require('../img/DLD2.jpg')} /></div>
                  <div className="eventdetail">
                    <div className="dates-on">
                      <span>12</span>
                      <p>May</p>
                    </div>
                    <div className="gtm-para">
                      <span>Future Of Cities - DLD NYC</span>
                      <p>8:00 am to 2:00 pm at Knotel Bryant </p>
                    </div>
                  </div>
                </li>
                <li>
                  <div className="img-block"><img src={require('../img/health.jpg')} /></div>
                  <div className="eventdetail">
                    <div className="dates-on">
                      <span>25</span>
                      <p>Apr</p>
                    </div>
                    <div className="gtm-para">
                      <span>Health Tech Founders' Stories</span>
                      <p>6:30 pm to 8:30 pm at Knotel Bryant</p>
                    </div>
                  </div>
                </li>
                <li>
                  <div className="img-block"><img src={require('../img/Space.jpg')} /></div>
                  <div className="eventdetail">
                    <div className="dates-on">
                      <span>20</span>
                      <p>Apr</p>
                    </div>
                    <div className="gtm-para">
                      <span>When Do We Go To Space?</span>
                      <p>6:30 pm to 8:30 pm at Knotel Bryant</p>
                    </div>
                  </div>
                </li>
              </ul>
            </div>
          </div>
        </div>
        <footer>
          <div className="footer">
            <div className="img-footer">
              <img src={require('../img/knotel.svg')} />
            </div>
            <ul>
              <li><a>Careers</a></li>
              <li><a>Terms</a></li>
              <li><a>Tenant Reps</a></li>
              <li><a>I have space</a></li>
            </ul>
            <div className="Copyright-res">Copyright © 2017 KNOTEL. All rights reserved.</div>
          </div>
        </footer>
      </div>
    )
  }
}

Upvotes: 1

Views: 615

Answers (3)

Armin
Armin

Reputation: 232

The other answers are correct, but you can also add the events to the higher order <div>

so you can modify your component to be like

return (
  <div onMouseOut={this.onMouseOut} onMouseOver={this.onMouseOver}>
      ...
  </div>
);

Upvotes: 0

Guy
Guy

Reputation: 535

From the docs:

You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.

This is not React-specific behavior; it is a part of how functions work in JavaScript.

So you need to bind this to your methods to in order to make it work.
This is how your constructor should look:

constructor(props) {
  super(props);
  this.state = {
   header: "harry header",
   content: "content for harry",
   activeClass: "normal",
   hovered: false
  }
  this.onMouseOver = this.onMouseOver.bind(this)
  this.onMouseOut = this.onMouseOut.bind(this)
}

Upvotes: 4

Mukesh Soni
Mukesh Soni

Reputation: 6668

You need to bind you class methods to this instance. One way to do that is in the constructor -

 constructor(props) {
      super(props);

      this.onMouseOver = this.onMouseOver.bind(this)
      this.onMouseOut = this.onMouseOut.bind(this)
      this.state = {
       header: "harry header",
       content: "content for harry",
       activeClass : 'normal',
       hovered :false
      }
   }

Whenever you get an error which you can trace back to cannot read property x of null where null was supposed to be this, you know that the binding for this is not correct at the time the method/function was called.

Upvotes: 2

Related Questions