0

I'm following relatively closely the tutorial of react-redux but decided to write my presentational component as a class. As you can see in the following code I wrote a submitHandler which should call the submitHandler mapped by react-redux' connect(). But when I call it, it results in TypeError: Cannot read property 'props' of null.

Any suggestions?

Container Component

import { connect } from 'react-redux'
import New from './New'
import { newEntry } from '../../store/actions'

function mapStateToProps(state) {
  return {
    value: state.currentEntries[state.currentEntries.length - 1].value,
    min: state.currentEntries[state.currentEntries.length - 1].value,
    max: 148
  }
}

function mapDispatchToProps(dispatch) {
  return {
    onSubmit: (date, value) => {
      dispatch(newEntry(date, value))
    }
  }
}

const NewContainer = connect(
  mapStateToProps,
  mapDispatchToProps
)(New)

export default NewContainer

Presentational Component

import React from 'react'
import moment from 'moment'

export default class Chart extends React.Component {
  submitHandler(e) {
    e.preventDefault()

    // BUG: Results in "TypeError: Cannot read property 'props' of null"
    this.props.onSubmit(this.date.value, this.number.value)

    this.date.value = moment().format('YYYYY-MM-DD')
    this.number.value = this.props.min
  }

  render() {
    const { value, min, max } = this.props

    return (
      <form className="New" onSubmit={this.submitHandler}>
        <input type="date" ref={node => { this.date = node}} defaultValue={moment().format('YYYYY-MM-DD')} />
        <input type="number" ref={node => { this.number = node }} min={min} max={max} defaultValue={value} />
        <button>Save</button>
      </form>
    )
  }
}
Simon Knittel
  • 1,730
  • 3
  • 15
  • 24

2 Answers2

2

You just need to bind your submit handler:

 <form className="New" onSubmit={this.submitHandler}>

Should be:

 <form className="New" onSubmit={this.submitHandler.bind(this)}>

Or:

 <form className="New" onSubmit={(e) => this.submitHandler(e)}>

The difference with a class component is that methods do not auto-bind this.

Davin Tryon
  • 66,517
  • 15
  • 143
  • 132
1

Try this!

import React from 'react'
import moment from 'moment'

export default class Chart extends React.Component {
  submitHandler(e) {
    e.preventDefault()

    // BUG: Results in "TypeError: Cannot read property 'props' of null"
    this.props.onSubmit(this.date.value, this.number.value)

    this.date.value = moment().format('YYYYY-MM-DD')
    this.number.value = this.props.min
  }

  render() {
    const { value, min, max } = this.props

    return (
      <form className="New" onSubmit={this.submitHandler.bind(this)}>
        <input type="date" ref={node => { this.date = node}} defaultValue={moment().format('YYYYY-MM-DD')} />
        <input type="number" ref={node => { this.number = node }} min={min} max={max} defaultValue={value} />
        <button>Save</button>
      </form>
    )
  }
}
Aftab Khan
  • 3,853
  • 1
  • 21
  • 30