usednapkin
usednapkin

Reputation: 37

Uncaught TypeError: Cannot read property 'setState' of null

I'm new to using react and have run into the issue stated:

Uncaught TypeError: Cannot read property 'setState' of null.

Basically what I am trying to do is, a user can click on three different headlines, and on click, it will render a certain template specific for that headline. This is the code I'm currently using that gave me this error:

class Selection extends React.Component {

constructor(props) {
    super(props);
    this.state = {selections: [], donateActive: true, fundraiseActive: false, speakActive: false };
}

componentDidMount() {
    this.setState({
        selections: selectionData.selections
    })
}

componentWillUnMount(){
    console.log("unmounted!"); 
}

donateOnClick() {
    this.setState({ donateActive: true, fundraiseActive: false, speakActive: false});
}

fundraiseOnClick() {
    this.setState({ fundraiseActive: true, donateActive: false, speakActive: false});
}

speakOnClick() {
    this.setState({ speakActive: true, fundraiseActive: false, donateActive: false});
}

donateTemplate() {
    return (
        <div>
            <h1>donate template</h1>
        </div>
    )
}   

fundraiseTemplate() {
    return (
        <div>
            <h1>fundraise template</h1>
        </div>
    )

}

speakTemplate() {
    return (
        <div>
            <h1>speak template</h1>
        </div>
    )
}

render() {
    return(
        <div>
            <div className="col-sm-6 col-sm-push-6 right">
                <div className="right-content-container">
                    <div className="selections">
                        <h3>You can</h3>
                        <h1 onClick={this.donateOnClick} className="selection active" id="selection-donate">donate</h1>
                        <h1 onClick={this.fundraiseOnClick} className="selection" id="selection-fundraise">fundraise</h1>
                        <h1 onClick={this.speakOnClick} className="selection" id="selection-speak">speak up</h1>
                        <hr></hr>
                    </div>
                    <div>
                        {
                            if (this.state.donateActive) {
                                this.donateTemplate()
                            }
                            if (this.state.fundraiseActive) {
                                this.fundraiseTemplate()
                            }
                            if (this.state.speakActive) {
                                this.speakTemplate()
                            }
                        }
                    </div>
                </div>
            </div>
            <div className="col-sm-6 col-sm-pull-6 left">
                <div className="left-content-container">
                    <img className="img-responsive hidden-xs" src="./images/selections/.jpg" alt=""/>
                    <img className="img-responsive hidden-sm hidden-md hidden-lg" src="./images/selections/.jpg" alt=""/>
                </div>
            </div>
        </div>
    );
}


}

Additionally, I'm not sure if I am able to use IF statements inside of return() the way I am doing right now inside of the render() method, is there a better way to do this?

Any help would be greatly appreciated.

Upvotes: 4

Views: 5400

Answers (2)

taylorc93
taylorc93

Reputation: 3716

Your problem relates to this binding. React doesn't automatically bind the React component to the value of this, except for the constructor and lifecycle methods. To fix this, in your constructor, add this for each function you want to bind this for

constructor(props) {
  super(props);
  this.donateOnClick = this.donateOnClick.bind(this);
  // other function bindings
}

As for your if statement question, as long as the if statements are wrapped in {}, you can use them. The curly braces indicate to the JSX parser that anything inside of them should be evaluated as javascript, so any valid javascript can be placed inside of them.

UPDATE: Not sure why those if statements are throwing an Unexpected token error, but try this:

<div>
    { this.state.donateActive ? this.donateTemplate() : null }
    { this.state.fundraiseActive ? this.fundraiserTemplate() : null }
    { this.state.speakactive ? this.speakTemplate() : null }
</div>

That's using the ternary if statement. If you're unfamiliar with the syntax: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator

If that doesn't work, please update your question with a more detailed error message. In particular, I'd be curious to see what token it's saying is unexpected

Upvotes: 7

Diogo Sgrillo
Diogo Sgrillo

Reputation: 2701

You can also autobind your methods in your class if you declare them like this:

donateOnClick = () => {
    this.setState({ donateActive: true, fundraiseActive: false, speakActive: false});
}

fundraiseOnClick = () => {
    this.setState({ fundraiseActive: true, donateActive: false, speakActive: false});
}

speakOnClick = () => {
    this.setState({ speakActive: true, fundraiseActive: false, donateActive: false});
}

Upvotes: 1

Related Questions