A Committed Intro Guide to ReactJS, Part 2

Thomas Collardeau
7 min readApr 8, 2018

--

Welcome back! In part 1, we teamed up and bootstrapped a new app with create-react-app, a mock database, and some simple CSS rules; in order to focus on front-end development with ReactJS. We familiarized ourselves with the essential state and setState of the almighty React component.

There is a dedicated Github repo for this blog series. The commit history follows the steps taken in this guide. Feel free to fork the repo and checkout any commit to experiment along with this series, if you haven’t already created your own repo in part 1, that is.

Finally, we’re working from a small list of features, of which we took care of the first: our app starts out with a “loading…” text rendered on the screen.

Requirements:
X) display a loading text (while “fetching” todos) — done!
2) load and display todos
3) add new todos
4) toggle todos done/undone
5) delete todos

Let’s do some coding!

Picking Up Where We Left Off

We had a single component living in src/App.js, on which we assigned our first state that we called loaded:

We shall update the state of our app

Fetching Todos and Updating State

Our next task is to fetch todos from our mock DB and display them on the screen. We’ll create a function right on the class component, so we have access to this.setState, and we’ll call it syncTodos. It will call our mockDB, give us some todos (after a 500ms delay), and then again every time there is an update in the database. We can merrily set the new state in the db.syncTodos callback. Check it out:

creating a first action

We’re setting an initial state for our todos on line 6, then we’re defining a syncTodos action on line 11 (under an actions key I decided to make to keep all setState functions together).

Calling this.actions.syncTodos will trigger db.syncTodos with a callback function that we pass in, which gives us the todos each time the data changes in the db (like a realtime database a la Firebase). So we’re repeatedly receiving the todos in the callback, which is an object of todos. We take that, and use our friend setState, of course, to trigger a re-render with the updated data!

But wait, we’ve only described the action here. Where do we call it? Where do we call actions.syncTodos() and get the party started? We want to fetch our todos as soon as our app mounts… without any further prompt or feedback from the user other than the fact they started the app.

Lifecycle Hooks

Well, React gives us lifecycle hooks. Let’s take a look at one in particular, componentDidMount:

componentDidMount is a React lifecycle method

We have componentDidMount available to us as a lifecycle hook right on the React class component. It is called just once when the component mounts, as one might intuitively expect. So right there, we can call our syncTodos action and it will set things into motion (with a call to our db which in turns will call setState). Let’s see the result of the console.log(this.state):

console.log(this.state) in the render function

The console.log was called twice, once on the initial render with the default state, and then again as a result of our setState originating in componentDidMount, and now we have an object of todos on our React state!

In order to actually render the todos on the screen, we’ll need to have them in an array to iterate over them. We’ll sort the todos by ts (timestamp) while we’re handling this data. It will be nice to have the most recent item on top of the list. Let’s implement:

React is just a lot of JavaScript

Let’s refactor this already, so we extract the logic into their own functions. Functions are good. We can reuse and test functions!

creating a todoList array sorted by timestamp

Pretty neat! We’ve initiated a new state todoList as an empty array on line 10 (it’s always a good idea to have initial state. Bad things could happen if the todoList is undefined in your first rendering). In our syncItems action on line 20 we are now deriving a todoList from todos and setting it right on the React state. Let’s look at our state in the console now:

todoList has our 2 pre-loaded todos!

We now see our todoList. First log is the initial state so it’s an empty array, but in the second log we have our two todo items, sorted and ready for render!

Render an Array of Data

Let’s render the todoList we just concocted. We actually use pure JS with Array.prototype.map inside the JSX.

rendering an array with .map

In order to run a JavaScript expression within the JSX syntax you have to do it inside curly braces {...} hence we wrap the whole thing. We .map over the array todoList to iterate through the todos and render a div for each of them. Each mapped element in React must have a unique key so we assign todo.id there, and we render the todo.title inside the div. Now we have our two todos displayed on the screen. Hooray!

Let’s commit our changes, shall we?

Functional Components

Let’s check out our render function in App.js as it stands now:

Inside our one and only component so far

You can imagine that as our UI grows, we don’t want to tack on all of our code in this single component. We want to break our code into small parts, and snap them together like legos. To this end, we can use a component in a component and pass it whatever properties we want, for example:
<MyComp loaded={false} />.
We just have to create MyComp of course.

There are two ways to create a component. The first, we’ve already seen, it’s the one we’re using currently: the class component which extends React.component. The other is a more barebones version, the functional stateless component. We’ll make a separate component now for our todos-related UI, take a look at the changes:

Todos is a stateless component

We now refer to our sparkling new <Todos /> component in the render function of our App, and we pass in the entire state (with the spread syntax, bundled up for us via babel): <Todos { …this.state } />

Let’s look at the component itself: Todos on line 41. It’s a normal JS function, but it returns JSX! In fact, it returns whatever render would have returned in a class component. And that’s actually all you can do with a stateless component. You cannot add some state or call a lifecycle method on it. They’re just functions. They’re efficient and very handy to use because you can think of your UI as a composition of functions.

Moreover, we would be wise to minimize our use of class components because we shouldn’t track state in too many different places at once if we want to keep our sanity in check. The way that we have one single class component at the top of the app right now is quite nice to begin. Let the data (state/props) flow down from the top of the app.

Finally, you can see how Todos receive props (properties) from its parent component and uses them to render its own JSX. props is really just a copy of the App state here in our example.

Ok let’s check in this housekeeping change:

Taking Stock of Our Progress

Let’s update our feature list, as it would appear we’re done with the 2nd item :)

Requirements:
X) display a loading text while fetching todos — done
X) load and display todos — done
3) add new todos
4) toggle todos done/undone
5) delete todos

How are you feeling about our progress? Let’s take a short break, shall we?

In part 3, we’ll bravely march on. We’ll start by creating a controlled text input to enable the ability to create brand new todos!

In the interim, why not take a look at the history of React: https://blog.risingstack.com/the-history-of-react-js-on-a-timeline/

[update]: Part 3 is now available.

Thanks for reading! Feedback is appreciated!
You can follow me on Twitter.

Photo Credit: “A brown mug next to a MacBook with lines of code on its screen” by Artem Sapegin

--

--