1

I am working on a very simple react application. It has a component and in this component I am trying to set the state when a link clicked. But for some reason setState is not even getting recognized. It is getting underlined which says unresolved function or method setState(). I have no idea why it is not getting recognized. This is the first time I am trying to use setState in this application.

import React, { Component } from 'react';
import { push } from 'react-router-redux'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'

const styles = require('./sidebar.css');

class MenuPanel extends Component {

   constructor(){
       super();
       this.state = {
           activePanel: "trivia"
       }
   }

    toImagePage(){
       this.setState({activePanel:"image"})
        console.log("hey")
    }

    render() {
        return (
            <div>
                <div className="navbar-side">
                    <div className="tessact-logo"></div>
                    <div className="navbar-item active" onClick={() => this.props.toTriviaPage()}>
                        <a className="navbar-item-link"><span className="fa fa-comment"></span> TRIVIA</a>
                    </div>
                    <div className="navbar-item" onClick={() => this.toImagePage()}>
                        <a className="navbar-item-link"><span className="fa fa-picture-o"></span> IMAGES</a>
                        <div className="navbar-item-inside">
                            <a className="navbar-item-inside-link">PERSONSS</a>
                            <a className="navbar-item-inside-link">BRANDS</a>
                            <a className="navbar-item-inside-link">OBJECTS</a>
                        </div>
                    </div>
                    <div className="navbar-item">
                        <a className="navbar-item-link"><span className="fa fa-tags"></span> KEYWORDS</a>
                    </div>
                </div>
            </div>

        );
    }
}


const mapDispatchToProps = dispatch => bindActionCreators({
    toTriviaPage: () => {
        this.setState({activePanel:"trivia"})
        push('/trivia')
    }, dispatch)


export default connect(
    null,
    mapDispatchToProps
)(MenuPanel)

enter image description here

enter image description here

ArbitB
  • 113
  • 3
  • 12

4 Answers4

3

Error is because of this code:

const mapDispatchToProps = dispatch => bindActionCreators({
    toTriviaPage: () => {
        this.setState({activePanel:"trivia"})
        push('/trivia')
    }, dispatch)

Inside toTriviaPage setState will not be available.

To solve the problem you can do one thing, create a local function inside component do setState inside that then call the props function and do the other operation.

Like this:

onClick={() => this.localFunction()}

localFunction(){
    this.setState({activePanel:"trivia"}, () => {
        this.props.toTriviaPage();
    })
}
Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
  • Mayank the problem is setState is not even getting recognized here. You see that underline, that is an issue. Other wise toImagePanel should work right? – ArbitB Jan 26 '18 at 15:40
  • not sure about the underline, but that code is proper don't worry about that, check the error message : 'this.setState is not a function at toTriviaPage', cause of error is setState inside `toTriviaPage` method. – Mayank Shukla Jan 26 '18 at 15:44
  • Okay it is working in toImagePanel. But the problem is when I click on Image for the the first time, the activePanel state remains to "image" only. When I click on Image for the second time and thereafter, the state changes to "image". Why so? It should change in the first click only, right? I am consoling (this.state.activePanel) in toImagePanel only, just after setting state. – ArbitB Jan 26 '18 at 15:46
  • Check this answer, this is because [**setState is async**](https://stackoverflow.com/questions/42593202/why-calling-setstate-method-doesnt-mutate-the-state-immediately/42593250#42593250), to check the updated value just after setState use callback method. If you check inside render method it will print the proper value :) – Mayank Shukla Jan 26 '18 at 15:52
  • Thanks Mayank. Solved the issue. – ArbitB Jan 26 '18 at 15:55
2

You are trying to use setState outside of the context of your class. The error is not in toImagePage method.

The error is in the function mapDispatchToProps. You can't use setState there.

Move toTriviaPage into your component and bind the this context or use an arrow function.

mapDispatchToProps parameter of connect is used to dispatch redux actions which you don't.

toTriviaPage = () => {
    this.setState({ activePanel: "image" });
    push('/trivia');
}
Timo Jokinen
  • 707
  • 7
  • 26
  • I already tried that. Infact to toImage is in component only and still setState is not working there also – ArbitB Jan 26 '18 at 15:39
  • You are extending your MenuPanel class with Component from React which contains setState. Unless you don't forget to bind the context this.setState should work. – Timo Jokinen Jan 26 '18 at 15:41
1

You will need to bind your methods to the constructor unless you use arrow function.

this.toImagePage = this.toImagePage.bind(this)
philipjc
  • 241
  • 3
  • 9
0

It is considered best practices to use arrow functions on methods on the class because you do not change the context of this. When you don't use arrow functions the scope of this is limited to the method specifically, which is why you have to bind it.

So as stated in other answers you either have to bind it, or use arrow functions.

bdurb
  • 71
  • 3