This post explains the construction of a simple React web application. The app we want to design is basically a React clone of the email client in Ember's home page. It won't send email, or communicate with a backend to pull a list of emails, it's just a bit of static data with some Bootstrap styling.
August 2018: Please note that this post was written for an older version of React. Changes in the code might be necessary to adapt it to the latest versions and best practices.
Each component is, as always, a visible, semantic element on the screen. We have components to represent an email, a list of emails, the list of mailboxes, and a general component for when no email or mailbox has been selected. I've highlighted component structure, as the React examples do, in this image:
The interface is precisely what you'd expect. There's a list of mailboxes (Inbox, Spam), when you click on one it updates the list of emails, and when you click on an email from the list it displays its metadata and body.
First things first: The
This is just a
div with a definition list of the various props, nothing that requires an explanation. We embed the raw HTML body using React's
Now, the list of emails. Which is actually rendered as a table, but semantically is a list. Let's first go through the list itself:
The render function iterates over the email list, collecting (Or it 'maps over')
EmailListItem components, passing some initial props to them. There are two props here that matter:
key: This is a prop that you pass to every list item when building lists in react. It can simply be the index (Which the map function provides), or a more domain-specific identifier.
on_click: This prop sends a function that's passed from even higher up down to the . We use bind to partially apply the function.
EmailListItem component looks like this:
Here we use React's
onClick prop to declare that when that table row is clicked, the
on_click prop should be called.
Here we take a slight detour to make a small, reusable component which we'll use whenever we let the user choose an element from a list, to represent the initial state when no element is chosen. The
NoneSelected component uses a single prop, text.
Now, we build a
Mailbox component we can use to display the current email and the list of emails. The
Mailbox has only one item of state: The ID of the selected email, which is either a natural number or null. A method,
handleSelectEmail, will be passed down the component hierarchy as a callback for the
onClick event of an
The render functions is very simple: If an email is selected, it filters its data out of the props and instantiates a corresponding
NoneSelected. Then the email list and selected email are displayed.
And now the list of mailboxes. This isn't too complicated, the render function just maps over its props to create an array of list items, which it embeds in the JSX.
App component ties everything together. Like the
Mailbox component, this has an ID (state) and a method to track the currently selected mailbox. The render function is essentially the same as well: It renders a
Mailbox list, and if a mailbox is selected, it renders it, otherwise it renders a
We’ll use the following fixtures for our mailboxes and emails:
We render the app into the document’s body, using the fixtures as the list of mailboxes.
Finally, we add a little style:
And that’s it. That’s the simplest react application with some actions and more than a couple components. You can find the source code as a single file in the
react-examples repository, along with code to run it, the CSS stylesheet, and another example which will be the subject of the next React blog post.
Callbacks are passed down through the component hierarchy by props, and actions climb their way back up to the component that handles them. For instance, when selecting mailboxes:
Appcomponent has a method,
handleSelectMailbox, which takes a mailbox ID and sets the app’s current mailbox ID to it.
MailboxList, it’s bound to null and assigned to the
onClickevent prop of the mailbox list item.
The repetition (Passing things again and again) rather violates DRY, but it’s not hard to follow after an initial look through the code.