Code refactor and corrections

Linked Projects:

Calreact
 
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.

Liked this tutorial? Get more like this in your inbox