This lesson was part of the The Complete React on Rails 5 Course.

A new version of the course is now available

Get the full course

You're viewing a lesson from an old course. Click here to get access to the new version.

Code refactor and corrections

Hrishi Mittal

This video was part of the The Complete React on Rails 5 Course.

A new version of the course is now available

Enrol now to view this video

Lesson code - https://github.com/learnetto/calreact/tree/m6l3-refactor

Before proceeding with the app further, I want to refactor some bits of our code to make it less confusing and to improve performance.

First, we’ll remove the input_ prefix from our prop names and form fields. I’ve renamed them from input_title and input_app_time to title and appt_time, respectively:

// AppointmentForm.jsx
<input name='title' placeholder='Appointment Title'
    value={this.props.title}
    onChange={(event) => this.handleChange(event)} />

// Appointments.jsx
<AppointmentForm title={this.state.title}
  appt_time={this.state.appt_time}
  formValid={this.state.formValid}
  onUserInput={(obj) => this.handleUserInput(obj}
  onFormSubmit={() => this.handleFormSubmit()} />

Next, in the AppointmentForm component, we need to wrap the value prop for Datetime  inside  moment() function call, otherwise it doesn’t get set correctly.

So first we need to import moment:

import moment from 'moment';

and set the Datetime value by calling moment():

<Datetime input={false} open={true} inputProps={inputProps}
  value={moment(this.props.appt_time)}
  onChange={(event) => this.setApptTime(event)} />

Let’s also delete this HelloWorld.jsx file from the components directory. We don’t really need it.
[screenshot]

Next, let’s rename the jsx component files to follow the React convention of using PascalCase names, like we’re already doing in the FormErrors component.

Then I want to do a quick refactor of the callback methods in our components.

First, let’s look at the AppointmentForm component.

<form onSubmit={(event) => this.handleSubmit(event)}>
  <input name='title' placeholder='Appointment Title'
    value={this.props.title}
    onChange={(event) => this.handleChange(event)} />

  <Datetime input={false} open={true} inputProps={inputProps}
    value={moment(this.props.appt_time)}
    onChange={(event) => this.setApptTime(event)} />

  <input type='submit' value='Make Appointment'
    className='submit-button'
    disabled={!this.props.formValid} />
</form>

The way we have defined our callbacks now is not ideal because we are creating a new function every time the component is rendered.

Instead of doing that, we can simply write this.handleChange instead of using  {(event) =>

<input name='title' placeholder='Appointment Title'
  value={this.props.title}
  onChange={this.handleChange} />

And then define handleChange as an arrow function:

handleChange = (e) => {
  const name = e.target.name;
  const obj = {};
  obj[name] = e.target.value;
  this.props.onUserInput(obj);
}

And then the same with setApptTime and handleSubmit:

handleSubmit = (e) => {
  e.preventDefault();
  this.props.onFormSubmit();
}

setApptTime = (e) => {
  const name = 'appt_time';
  const obj = {};
  if(obj[name] = e.toDate()) {
    this.props.onUserInput(obj);
  }
}

...

<form onSubmit={this.handleSubmit}>
  <input name='title' placeholder='Appointment Title'
    value={this.props.title}
    onChange={this.handleChange} />

  <Datetime input={false} open={true} inputProps={inputProps}
    value={moment(this.props.appt_time)}
    onChange={this.setApptTime} />

  <input type='submit' value='Make Appointment'
    className='submit-button'
    disabled={!this.props.formValid} />
</form>

Then we can refactor the Appointments component.

Let’s change onUserInput and onFormSubmit to this.handleUserInput and this.handleFormSubmit, respectively:

<AppointmentForm title={this.state.title}
  appt_time={this.state.appt_time}
  formValid={this.state.formValid}
  onUserInput={this.handleUserInput}
  onFormSubmit={this.handleFormSubmit} />

And also the method definitions above:

handleUserInput = (obj) => {
  this.setState(obj, this.validateForm);
}

...

handleFormSubmit = () => {
  const appointment = {title: this.state.title, appt_time: this.state.appt_time};
  $.post('/appointments',
          {appointment: appointment})
        .done((data) => {
          this.addNewAppointment(data);
          this.resetFormErrors();
        })
        .fail((response) => {
          this.setState({formErrors: response.responseJSON})
        });
}

All the other components are fine.

This lesson was part of the The Complete React on Rails 5 Course.

A new version of the course is now available

Get the full course