jdfolino
jdfolino

Reputation: 327

React Redux cannot access props from method in onClick

I have the following for my index.js. I have set up React with create-react-app. I then installed redux and react redux.

import React from 'react';
import ReactDOM from 'react-dom';
import AppContainer from './AppContainer';
import {createStore} from 'redux'
import {Provider} from 'react-redux'

const defaultState = {
    activeTab: 'firstTab'
};

const reducer = function(state=defaultState, action){
    switch (action.type) {
        case 'TAB_CHANGED':
            return state.merge({
                activeTab: state.activeTab
            })
        default: return state;
    }
};
const store = createStore(reducer);

ReactDOM.render(
    <Provider store={store}>
        <AppContainer />
    </Provider>,
    document.getElementById('root')
);

and the following for my AppContainer.js

import React from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux'

class AppContainer extends React.Component {
  static propTypes = {
      activeTab: PropTypes.string.isRequired,
      dispatch: PropTypes.func.isRequired,
  }

  doSomething = function(){
      this.props.dispatch('TAB_CHANGED', {activeTab: Math.random().toString(36).substring(7)})
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <h1 className="App-title">{ this.props.activeTab }</h1>
        </header>
        <p className="App-intro">
            <button onClick={this.doSomething}>Do Something</button>
        </p>
      </div>
    );
  }
}

function mapStateToProps(state){
    return state;
}

export default connect(mapStateToProps)(AppContainer);

The page loads fine when first rendered. The react dom can access the this.props.activeTab. however when I click on the Do Something button I get the following error: TypeError: Cannot read property 'props' of undefined

Upvotes: 2

Views: 1291

Answers (1)

Akhilesh krishnan
Akhilesh krishnan

Reputation: 799

You have to bind the doSomething function to the context of the component else it this will refer to the context of the render. So add the snippet to the constructor

constructor(){
    super()
    this.doSomething = this.doSomething.bind(this);
}

or ES6 - declare doSomething as an arrow function and there will be no need for bind in the constructor

constructor(){}
doSomething = () => {
....
}

Upvotes: 3

Related Questions