React props and nested components

Linked Projects:

Calreact
 

Lesson code - https://github.com/learnetto/calreact/tree/lesson-3.2

Now, we're going to build this appointments app in React.

I've added some more appointments so that we have a bit more data to play with.

We'll need 4 React components:
  1. the form
  2. the list of appointments
  3. each individual appointment
  4. and also, a container component around all those components

Let's start off by first creating an Appointments component.

I am going to go back to a React component we've built in the previous lesson, called Appointments, where we simply display the title of the app in the <h4> tag. Let's replace that with the <div> tag.

And we are going to use that component in index.html.haml. We'll replace the form code with the React component Appointments and then pass it a prop called appointments.

= react_component('Appointments', appointments: @appointments)

And we can use that prop in the Appointments component:
var Appointments = React.createClass({
  render: function() {
    return (
      <div>
        {this.props.appointments.map(function(appointment) {
          return (
            <div>
              <h3>{appointment.title}</h3>
              <p>{appointment.appt_time}</p>
            </div>
          )
        })}
      </div>
    )
  }
});

map() is a Javascript function which takes an array, applies a function to each of its elements and returns a new array with the results.

We loop through the appointments and for each one, we add an h3 tag with the title and in the next paragraph, the appointment time.

Notice that we are enclosing these values in curly braces, that's a part of JSX syntax.

We enclose that in a <div>. And we need to return this bit of markup.

Try to remember the basic idea: that a React component gives you a function which takes some data and returns a piece of UI.

Now, if we refresh the page, we can see the list of appointments. 
So our first React component works.

Now, each of these appointments can also be a component. It's a good practice to keep your React components as small and self-contained as possible, so that you can make changes which only affect the part of UI that you want to change.

So, if we make a separate Appointment component, we can edit it later without having to change the outer Appointments component.

Let's take this code and put it in a new component, called Appointment, singular, and let's save this as appointment.jsx.

Again, we'll define a variable called Appointment, and call
React.createClass()
Add a render method which will return the markup.
Let's copy and paste that in here.

We'll need to pass in the appointment data as a prop. So, let's add this.props here.

And now, we can replace this with our new Appointment component, and pass it a prop called appointment.

But, we hit an error! Let's see what we need to fix.

Ah, yes! This shouldn't be a function, we just have to pass an object.
Also, this value needs to be inside of curly braces.

Now, let's reload the page. And there is our list of appointments.

Next, let's add a component for the form.

We'll call it AppointmentForm. So, again we use it just like any tag, AppointmentForm, then a close tag, and save it as appointment_form.jsx.

Then, call the
React.createClass()
and an object inside, and then render function. 

So, what does this render function needs to return? It needs to return a form, which is gonna have 3 elements.

So let's add the <form> tag, a </form> close tag.

So the first <input> field will be for the appointment title, let's call it a title and a placeholder text, just simple 'Appointment Title'.
Then we need another <input> field for the appointment time, and some placeholder text 'Date and Time'.
And finally, a form submit <button>, for which we can add the text 'Make Appointment'.
Let's also add the title to the top, 'Make a new Appointment'.

Again, remember, we need to enclose all of this inside one outer tag, so let's just use a <div> tag here.

And that's our AppointmentForm component.

So let's see if we can see it on a page. Refresh.
There it is, we have our form on the page as well.

Let's clean this up a little bit so that this list of the appointments is also a separate component.

Let's take this bit of code, and put it in a new component, called AppointmentsList.
Now, we can use it here, 'AppointmentsList, and let's pass it the appointments data as a prop.

So,
appointments = { appointments }

Now, each Appointment component is nested inside the AppointmentsList component. So, that's a lot cleaner.

Now, we got our container component called Appointments which contains the AppointmentForm, and AppointmentsList components.

We need to change this to
this.props.appointments

Also, I just remembered that I forgot to add a return to the AppointmentsList component, so let's add that now. And we need to enclose it in the <div>.

Now, let's reload. Great, that works!

Now we got all our components set up. We've got a form component with two input fields and a submit button, and we've got a list of appointments, all nested inside the container appointments component.

And now for the fun part, let's make this form work!

Liked this tutorial? Get more like this in your inbox