Binding class methods

Binding class methods
WIP

Now that you know about state and events, it’s time to make your Add Contact form work!

But to start, we’ll wade in at the shallow end with a simple exercise.

All you need to do to make the below input work is add a single line in handleChange.

Once you’re done, we’ll discuss what that call to bind in the constructor does.

index.js
import React from 'react'
import ReactDOM from 'react-dom'

class InputContainer extends React.Component {
  constructor() {
    super()
    this.state = { value: "Edit Me!" }
    this.handleChange = this.handleChange.bind(this)
  }

  render() {
    return (
      <input
        onChange={this.handleChange}
        value={this.state.value}
      />
    )
  }

  handleChange(e) {
    // ...
  }
}

ReactDOM.render(
  <InputContainer />,
  document.getElementById('root')
)
Build In Progress

#Binding event handlers

Most event handlers in React need access to a component’s this object. And while that may seem painfully obvious, there is a good reason for saying it.

In JavaScript, a class’s methods are not guaranteed to have access to this.

One of the unfortunate things about JavaScript is that the value of this at any point is, well, it could be anything. There are rules, but they’re far too complicated for mere mortals. And as it happens, the behavior of this within event handlers usually isn’t what you’d expect.

Now there are a number of ways of fixing this. But the simplest fix is to bind each handler in the constructor, as demonstrated above.

#Let’s build a form!

You can manage an entire form’s state using the same patterns as above. The only difference is scale; as there are multiple inputs, you’ll need multiple event handlers.

I’ve started you off with the contact form component from earlier. But I’ve made one change: instead of accepting name and email props, they are read from this.state.

Your task is to connect the inputs to state via event handlers, so that you can type in them.

And since I’m feeling nice, I’ll give you a few hints:

  • If you see the message “Cannot read property ‘setState’ of undefined” in the console, make sure that you’re binding all of your event handler methods in the constructor, as demonstrated above.
  • If the editor is feeling a little cramped, try clicking the fullscreen button at the top right.
index.js
styles.css
import React from 'react'
import ReactDOM from 'react-dom'
import './styles.css'

class ContactForm extends React.Component {
  constructor() {
    super()
    this.state = {
      name: '',
      email: '',
    }
  }

  render() {
    return (
      <div className='ContactForm'>
        <label>
          <span>Name</span>
          <input value={this.state.name} />
        </label>
        <label>
          <span>E-mail</span>
          <input value={this.state.email} />
        </label>
      </div>
    )
  }
}

ReactDOM.render(
  <ContactForm />,
  document.getElementById('root')
)
Build In Progress

Did you manage to get it to work? If so, congratulations! If not, double check that you’ve bound your event handlers correctly. And if you do need to check the solution, make sure you get your code working afterwards. And once you do, congratulations!

This is an important exercise, as you’ll often come across this pattern in real React apps.

Of course, completing this exercise is still a little bittersweet. You have a working contact form — but it doesn’t have an add button. What kind of contact form is that?

You’re really close to being able to add contacts to your contact list from earlier. All that’s left is finding a way to get the contacts out of the form component.

Progress to next section.