Reputation: 501
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
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
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 bindthis.handleClick
and pass it toonClick
,this
will beundefined
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
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