One year with React

This is the final post in Bytesized’s A year with React.js series, which explores increasingly complex aspects of being a React developer. This post covers your first year with React components––component testing, future-proofing, and introducing data flow to your application, with Redux. It’s strongly recommended that readers start this series from the beginning, with the first post, “One hour with React”.

In this series, we’ve covered the basics of React components, but we pretty quickly moved past the basics of rendering HTML and writing component classes into the more complicated parts of the framework: component lifecycles, structuring your application, and looking towards the future with high-quality open-source tooling. In this final part of the series, we’ll continue to delve more into what it means to build a React application, one year in, that feels well-crafted. It might seem like over-optimizing to worry so much about well-crafted code. Clean Code, referenced in the previous post, has this to say about code that isn’t well-crafted:

If you have been a programmer for more than two or three years, you have probably been significantly slowed down by someone else’s messy code. If you have been a programmer for longer than two or three years, you have probably been slowed down by messy code. The degree of the slowdown can be significant. Over the span of a year or two, teams that were moving very fast at the beginning of a project can find themselves moving at a snail’s pace. Every change they make to the code breaks two or three other parts of the code. No change is trivial. Every addition or modification to the system requires that the tangles, twists, and knots be “understood” so that more tangles, twists, and knots can be added. Over time the mess becomes so big and so deep and so tall, they can not clean it up. There is no way at all.

As the mess builds, the productivity of the team continues to decrease, asymptotically approaching zero. As productivity decreases, management does the only thing they can; they add more staff to the project in hopes of increasing productivity. But that new staff is not versed in the design of the system. They don’t know the difference between a change that matches the design intent and a change that thwarts the design intent. Furthermore, they, and everyone else on the team, are under horrific pressure to increase productivity. So they all make more and more messes, driving the productivity ever further toward zero.

Every programmer would like to think that their code is well-crafted. But bad code doesn’t happen with huge, sweeping decisions about features. It happens each time we skimp on cleanly separating logic between modules. It happens when we leave a variable poorly named, or when we don’t implement error checking because it takes just a bit too long. It’s easy to point at a particularly complicated feature that was implemented quickly and say “This is why our application is bad!” My experience has always been quite the opposite: it’s when we revisit an old part of our application and decide that it’s not worth it to use the same coding style as our new work; when we see lazy code in code review and make a mental note to re-think it later, but don’t ever leave actual time to handle tech debt.

This problem has come to a head in what is now likely the most popular and fastest growing language in the world: JavaScript. The unique combination of the explosion of the internet and the deceptively simple style of the language has made web development a singularly approachable avenue for new programmers. The result is a generation of code that missed Clean Code; one where shipping is prioritized over crafting something with a long life.

Future-proofing

JavaScript is infamous as a fast-moving language. It’s a common jab on Hacker News to suggest that because a new hobbyist re-implementation of React has been released on GitHub, that every React team will drop everything and move to the new hotness. Consider Vue.js. In the last few years, Vue.js has become known as “the React killer”. Of course, React itself was “the Angular killer” or “the Ember killer” only a couple years ago! Vue itself is closer to Angular in design, but because of React’s current status as the most prominent or hyped framework in the JavaScript developer community, Vue has been touted as the next hot thing.

So while I audibly groan when I see someone make fun of JavaScript developers for jumping from bandwagon to bandwagon, this joke has its merits: the community has seen a huge amount of innovation in the last decade, and being a JavaScript developer in 2017 means something quite different than what it meant in 2007. A JavaScript developer pre-Node, pre-Angular, pre-React was someone using jQuery or something similar to enrich their HTML and CSS websites. When AJAX came along, JS developers began scratching the surface of fully interactive applications. In 2017, a JavaScript developer could be entirely removed from the browser, the application JS was designed for! A Node developer is handling the same complexity that backend developers were fifteen years ago, but with a programming language built with entirely different concerns.

It’s because of this unique combination of JavaScript’s increased scope and responsibility in the programming community and, frankly, its shortcomings as a language, that makes the idea of “future-proofing” your JavaScript applications such a pressing concern. It’s hard to say what the future of the language is: a few years ago, many JS developers were ready to move entirely to CoffeeScript full-time. When ES6, the newest version of JavaScript, began making its way into the hands of development teams, tools like Babel replaced CoffeeScript seemingly overnight. The developer experience for JavaScript can change constantly. I’m sure that at this point, even I’m a bit behind on what the latest and greatest is! But how does this affect React? Assuming that we stick with React and don’t jump ship to the hottest new framework, is this idea of churn, or the rate of change in technologies and frameworks, going to cause our React apps to stop working overnight?

The truth is that React has remained quite consistent in its lifetime. The original premise of React–providing a performant rendering engine for lightweight components–has stayed constant from version 0.1 to version 15, the current version at time of writing. The definitions and naming, like all software projects, saw some changes in the first couple years. Facebook’s wonderful “Our First 50,000 Stars” explores the first three-and-a-half years of the project, and acknowledges this problem–no doubt because of React’s status in the JS community, this rollout process was closely examined, and perhaps mocked by the community:

During the first year of React, internal adoption was growing quickly but there was quite a lot of churn in the component APIs and naming conventions:

  • project was renamed to declare then to structure and finally to render.
  • Componentize was renamed to createComponent and finally to createClass.

Notably, the render method, arguably the most important method for React components, went through four iterations to settle into what it is today. These kind of changes are to be expected in the initial life of a project. Compare that to the increasingly detailed and helpful CHANGELOG file for React releases, which almost always contains many multiples more of deprecation warnings and warnings over actual breaking changes. The framework itself is quite stable!

As for your applications themselves, building applications that can weather the storm of JavaScript churn can almost be reduced to simply focusing on writing clean, maintainable code. Given the immensity of the JavaScript developer community and ecosystem, it’s not surprising that there are dedicated resources to this very topic. Addy Osmani’s “Learning JavaScript Design Patterns” is a great resource, and also is entirely free on his website. Facebook’s own “Thinking in React” serves as almost a bible on the React state of mind. React, of course, also benefits from an incredibly active developer community. Projects like React Newsletter collect some of the best articles and projects in the React community every week, and can be thought of as taking the pulse of the current state of the ecosystem.

Component testing

Clean code, as we discussed in the previous post in this series, is about building things that work long-term. There is likely no better strategy for testing the long-term viability of your application than testing. Writing tests for your components is the best thing you can do to stabilize your application, and the React ecosystem provides an incredible variety of really effective tools to help writing tests not be a chore.

The most prominent of these is Jest, created by Facebook. Jest is designed to work out-of-the-box: in a world of complicated testing tools and developer experience, Jest is a breath of fresh air and makes beginning to write tests trivial. To confirm this, we’ll build a component using Test-Driven Development, and ensure that as we update it, the tests continue to pass, and provide us a stable application.

Earlier in this series, we used the concept of a blog application to model various components–the most important of these being, as you can imagine, a Post. A post, in our simple example, consists of just a title and content.

We’ll use the tool create-react-app to prototype components and their associated tests in this section. I’ve created a GitLab repo where you can download the source code–given a functioning npm install, you should be able to run npm install and npm test to run the tests locally. In the interest of brevity, I’ve removed import statements and npm install directives from the below code samples: please check the GitLab repository for a pre-made package.json file, and components with all the necessary modules imported. As we proceed through this example, relevant pieces of code will also be included below.

Post and HeaderText

class Post extends React.Component {
  render() {
    return (
      <div>
        <h1>Post title</h1>
        <p>Post content</p>
      </div>
    )
  }
}

To begin testing this component, we should first clarify what the desired behavior is. In the above example, there are two important pieces to the post: the title, and the content. Given the file Post.js, we’ll create a matching Post.spec.js test file, and populate it with our first test:

import React from 'react'
import ReactDOM from 'react-dom'
import Post from './Post'

it('renders a post', () => {
  const container = document.createElement('div')
  ReactDOM.render(<Post />, container)
})

Running npm test should confirm that the tests pass. For most machines, this command will setup functionality to re-run tests whenever a file changes in this directory: if this isn’t working for you, simply re-run npm test whenever we mention updates to files or tests.

In this simple test, we’ve just ensured that the Post component renders; it doesn’t check for any particular data, just that it doesn’t “blow up”, because of syntax errors or similar issues.

In the previous parts of this series, we’ve explored breaking down components into sub-components, for later re-use. To begin doing this, we’ll remove the h1 tag from Post, and replace it with a HeaderText component, which accepts text to display via the title prop.

class HeaderText extends React.Component {
  render() {
    return (
      <h1>{this.props.title}</h1>
    )
  }
}

class Post extends React.Component {
  render() {
    return (
      <div>
        <HeaderText title="My title" />
        <p>Post content</p>
      </div>
    )
  }
}

With the addition of HeaderText.js, we can also add specs, at HeaderText.spec.js, to ensure that the component renders as expected:

it('renders header text', () => {
  const container = document.createElement('div')
  ReactDOM.render(<HeaderText title="My title" />, container)
})

Snapshots

One of the most intriguing features recently added to Jest is snapshots. Snapshots read the structure of your component at the time of testing, and write the structure to a JSON file in your test directory. In doing this, you essentially get a free test in the future–a simple check to compare the new structure at the time of the test running, to the previously stored component structure. We’ll add tests to Post and HeaderText by including the renderer function from the react-test-renderer package, capturing the component structure, and matching it:

// Post.spec.js
it('matches the snapshot of a post', () => {
  const tree = renderer.create(<Post />).toJSON()
  expect(tree).toMatchSnapshot()
})

// HeaderText.spec.js
it('matches the snapshot of header text', () => {
  const tree = renderer.create(<HeaderText title="My title" />).toJSON()
  expect(tree).toMatchSnapshot()
})

This additional test should pass without incident. To test the snapshot behavior, we can change the title prop passed in:

// HeaderText.spec.js
it('matches the snapshot of header text', () => {
  const tree = renderer.create(<HeaderText title="My new title" />).toJSON()
  expect(tree).toMatchSnapshot()
})

In doing so, we can see that the new structure does not match the previously stored snapshot:

FAIL  src/HeaderText.spec.js
 - matches the snapshot of header text

   expect(value).toMatchSnapshot()

   Received value does not match stored snapshot 1.

   - Snapshot
   + Received

   @@ -1,3 +1,3 @@
    <h1>
   -  My title
   +  My new title
    </h1>

     at Object.<anonymous>.it (src/HeaderText.spec.js:20:16)
     at process._tickCallback (internal/process/next_tick.js:103:7)

This failure, luckily, is expected. In this case, we can simply press the “u” key, to update our failing snapshots. Given a different instance, this test might be unexpected, and simply having a snapshot saved us from headaches in the future.

Content

Finally, we’ll implement the Content component, which will accept a text prop and be the body of our blog post:

class Content extends React.Component {
  render() {
    return (
      <p>{this.props.text}</p>
    )
  }
}

Our Post component now contains two sub-components, each accepting dynamic values via props:

class Post extends React.Component {
  render() {
    return (
      <div>
        <HeaderText title="My title" />
        <Content text="My post content. Testing, testing!" />
      </div>
    )
  }
}

We’ll essentially copy and paste over the tests for Content.spec.js, building a simple “it renders” test, and a snapshot test:

it('renders content', () => {
  const container = document.createElement('div')
  ReactDOM.render(<Content text="My post content. Testing, testing!" />, container)
})    

it('matches the snapshot of content', () => {
  const tree = renderer.create(<Content text="My post content. Testing, testing!" />).toJSON()
  expect(tree).toMatchSnapshot()
})

Our new Content test passes, but now our previous Post snapshot test fails! This is, again, to be expected: internally, the structure of the Post component hasn’t actually changed (Content is, after all, just a p tag), but the text has changed. We’ll update the snapshots again with the “u” key.

Finally, I’d like to add one more function to the HeaderText component–the ability to pass in a CSS class name, to style the h1 tag depending on where it is being used. For instance, header text for a blog post will be much different than the header text used for a sidebar, or for the title of the blog itself. Let’s add an additional cssClass prop to HeaderText, passing it into the h1 tag or defaulting to the empty string "" if no cssClass is received:

class HeaderText extends React.Component {
  render() {
    return (
      <h1 className={this.props.cssClass || ""}>{this.props.title}</h1>
    )
  }
}

(Note-this code could be refactored by using React’s defaultProps functionality, to set cssClass to an empty string if it isn’t passed in directly. I’ll leave this as an exercise to the reader.)

When we save this file, we should see two test failures. Can you guess what they are? Both the Post component and the HeaderText component now fail, given that the structure of the h1 tag in HeaderText now includes a className prop. Update the snapshots to see that the tests should pass again.

We should actually ensure that the prop cssClass is being passed through. To do this, we’ll make use of the tool enzyme, a collection of React testing utilities from Airbnb. The most useful part of enzyme is the shallow function, which allows unit testing of individual components, as opposed to the entire child structure of a component. From the project’s README:

Shallow rendering is useful to constrain yourself to testing a component as a unit, and to ensure that your tests aren’t indirectly asserting on behavior of child components.

In this case, shallow rendering will allow us to simply check the first layer of HeaderText: although it doesn’t have any child components now, this may change in the future. With our shallowly-rendered component, we can find the h1 tag and confirm that the cssClass prop has been passed to the h1 tag as a class:

it('passes the cssClass prop to the header text class', () => {
  const component = shallow(<HeaderText cssClass="post-title" title="My title" />)
  expect(component.find('h1').hasClass('post-title')).toBe(true)
})

These tests give us a great starting point to continue to build out our blog application. As we add new features or components, our snapshots in particular will indicate how the application is changing from a UI perspective: we can either update the snapshots when known and expected test failures occur, or fix accordingly when a failed snapshot comparison is surprising or unexpected. Additionally, adding this testing process to a continuous integration tool, or as part of your code review process, can be an incredibly effective way to work with a team and build stable applications.

Introducing data flow to your application

Prototyping an application in React is really easy–building static components to template out how things will look can be done in even a matter of hours. When you begin to add dynamic pieces to your application that require retrieving and sending data, it’s very likely you’ll end up exploring tools like Redux or MobX. Both of these tools deal with the problem of managing state. State can be simple: instead of our above Post example having a hard-coded title and content text, it could be a JavaScript object:

{
  title: "My post title",
  content: "My post content"
}

A collection of posts is no different–instead of a single JavaScript object, our state becomes an array of objects:

[
  {
    title: "My post title",
    content: "My post content"
  },
  {
    title: "My newer title",
    content: "My newer post content"
  }
]

Dealing with this kind of state is straightforward: you could probably figure out how to render a collection of Post components fairly intuitively given this state, maybe doing something like:

const posts = getState(posts)
return posts.map(post => <Post title={post.title} content={post.content} />)

The above code, with the exception of the abstracted getState call, just creates a collection of Post components, filling in each title and content prop with the relevant field from the current post.

Given a more complicated application, managing state isn’t so clear. Consider this example, adapted from a React-based task manager application I was building last year:

{
  tasks: [
    {
      id: "5ec862a1-caca-4b45-b594-1fad523bc046",
      title: "Take the garbage out",
      context_id: "9a1d3479-ff8a-4f54-ae33-ffbca6b81760",
      project_id: "c1547e80-db77-4d32-8a80-00a8cac55122",
      created_at: "2017-03-12T09:14:43+00:00",
      updated_at: "2017-05-14T10:23:01+00:00",
      due_at: "2017-05-15T22:00:00+00:00",
    }
    // ... additional tasks
  ],
  contexts: [
    {
      id: "9a1d3479-ff8a-4f54-ae33-ffbca6b81760",
      name: "Home",
      created_at: "2017-03-01T09:10:01+00:00",
      updated_at: "2017-03-01T09:13:45+00:00",
    }
  ],
  projects: [
    {
      id: "c1547e80-db77-4d32-8a80-00a8cac55122",
      name: "Daily tasks",
      created_at: "2017-03-02T12:35:15+00:00",
      updated_at: "2017-03-02T12:35:15+00:00",
    }
  ],
  config: {
    hideSidebar: true,
    shiftReturnToConfirm: false
  },
  user: {
    authentication: {
      token: "<token>",
      expires_at: "2017-05-21T00:00:00+00:00",
    },
    id: "b9369559-ed1f-40a1-ab7f-32749766f351",
    name: "John Smith",
    email: "[email protected]",
  }
}

This example contains a great deal of complexity: the state itself can be represented as an object, but even one level deep we can already see a combination of arrays (tasks, contexts, projects) and objects (config, user). Abstracting getState before seemed easy; now, it’s worrying to not know how we’re retrieving state. Let’s briefly touch on Redux, to see how the basics of how it would handle managing something like the above state.

The first thing you’ll notice, out of neccesity, is the sheer size of the above state object. This object, condensed in the above example, contains all of a user’s tasks, projects, and contexts for a Getting Things Done application, as well as the authentication and configuration logic for the user themselves. For even a light user of this application, the state object consumed by the React application is quite large.

Redux is built to contain that state, and interface with it in a predictable way. In fact, predictability is likely the most important element of Redux, with the project’s homepage referring to it almost immediately:

I wrote Redux while working on my React Europe talk called “Hot Reloading with Time Travel”. My goal was to create a state management library with minimal API but completely predictable behavior, so it is possible to implement logging, hot reloading, time travel, universal apps, record and replay, without any buy-in from the developer.

Redux introduces a new aspect to React components–the concept of containers. Containers are components that interface with the application’s Redux store, which contains the application state. A Tasks container, for instance, would retrieve all of a user’s tasks from the store, and use them to render the individual Task components.

If you’re familiar with Getting Things Done or are just particularly quick, you might also notice that a task has a corresponding context and project. Therefore, it isn’t enough just for a Tasks container to know about tasks; it also needs to know about projects and contexts. Clearly, the problem of state management becomes complex almost immediately.

Redux is designed to be unidirectional: data flows a single direction, down. This means that data isn’t passed back and forth between components–a TaskForm component, where a user can edit a task’s name or other information, isn’t the “source of truth” for that task’s data across the application.

Imagine a simple Task component, with a checkbox to indicate the task is complete:

When you update the task to complete, where does the fact that this task is now complete get stored? Do other components, for instance, one that indicates how many incomplete tasks are available, now know that this task is complete? To solve this, there are two potential solutions:

  1. Each component listens to every other component, as needed. A IncompleteTasks component, which shows how many tasks are left to complete, listens to every Task component. When a Task component performs an update, every component watching that component also updates as needed.
  2. Each component receives state as needed, and when a change happens, any relevant updates come through the entire component structure, causing re-renders as needed.

My gut feeling when I began using Redux was that the first option was faster. Re-rendering sound expensive, after all! It turns out that Redux, which is described by the second option, is not only incredibly efficient, but a lot easier to reason about, and to work with on a day-to-day basis.

We’ve spent a lot of time talking about component trees: a Blog component contains many smaller components. In the same way, Redux state can be thought of as basically a tree, since it fundamentally is just a JavaScript object. Because of this, putting together components and state is like tying certain parts of the app to certain parts of the state tree. The aforementioned Tasks container needs to know about tasks, projects, and contexts: when we initialize the Tasks container, we simply pull out those parts of state, and pass them in as props:

class Tasks extends React.Component {
  retrieveProjectForTask(task, projects) {
    return projects.find(projects => project.id == task.project_id)
  }

  retrieveContextForTask(task, contexts) {
    return contexts.find(context => context.id == task.context_id)
  }

  render() {
    return this.props.tasks.map(task => {
      return (
        <Task
          context={this.retrieveContextForTask(task, this.props.contexts)}
          project={this.retrieveProjectForTask(task, this.props.projects)}
          task={task}
        />
      )
    })
  }
}

(Side-note: the savvy among you will recognize the above code as very inefficient. Don’t worry: I wouldn’t write something like this in production, and would substitute the retrieveProject/ContextForTask functions for a more efficient, likely hashtable-based solution. Take a deep breath!)

Our container knows about state, and knows what things the Task component needs to properly render. Instead of Task also needing to know about state, and how tasks, contexts, and projects all fit together, it simply receives task, context, and project, and takes what it needs from them:

Updating a task is conceptually simple, but perhaps out-of-scope for a detailed explanation at this point in the series (good thing we have a Redux series too–see below!). The gist is this: an action is passed into the Task component, which, when called, updates the Redux store at the top-level. When the update is successful, the new version of state is passed all the way down the component tree, ultimately resulting in the Task component that called the original action being updated. Instead of having components watch each other, all components, keeping in the common React theme, simply the output of a render function and their input, which is the updated state.

Looking for a deeper dive into Redux? Still not quite clicking? Be sure to check out our new Redux introduction series, Redux manufacturing.

Conclusion

This series has explored some of the lesser-talked about parts of React–there are a number of tutorials covering the basics of components, and build tooling, but not as many about why React is built the way it is, or how it lends itself to sturdy, long-lived code. This series is somewhat abstract in that way; we’ve looked at actual code in a variety of situations, from the basics, to writing tests, to our most recent peek at why we would consider Redux in more complex applications.

Still have questions? Check out the comment section below, or engage with the truly excellent React.js community on Twitter, GitHub, Stack Overflow, and a number of other places.

Want to receive this course in your email inbox? Join the A year with React.js mailing list–it’s instant and easy.

Bytesized offers technical training for companies. If you or your company want to take a more comprehensive dive into React.js, including hands-on workshops, lectures, and take-home exercises, contact us to schedule React.js training. We’re excited to work with you.

One month with React

This is part three in Bytesized’s A year with React.js series, which explores increasingly complex aspects of being a React developer. This post covers your first month with React––application structures and open-source libraries. It’s strongly recommended that readers start this series from the beginning, with the first post, “One hour with React”.

In the previous post in this series, we explored React components that render other components. In doing so, we begin to come up against the question: what does a well-crafted React application look like?

Exploring the concept of “good” code is a topic for another time, but most programmers know bad code when they see it. If they can’t sense it immediately, they will as they begin to work on it; that feeling of helplessness, where it’s unclear where to even begin with a new feature, or how to fix something that isn’t working. In this post, we’ll explore a single facet of good code–the concept of structure.

Well-structured code gives developers a vantage point into an application. With a well-structured application, it is clearer where a new feature should be built. It is more clear how an old feature is failing. A good structure, in short, lends itself to maintenance, not creation. The seminal programming book Clean Code has this to say on maintenance:

…in the auto industry, the bulk of the work lies not in manufacturing but in maintenance—or its avoidance. In software, 80% or more of what we do is quaintly called “maintenance”: the act of repair. Rather than embracing the typical Western focus on producing good software, we should be thinking more like home repairmen in the building industry, or auto mechanics in the automotive field.

If you’ve ever worked on a software project for more than a couple years, you’re likely intimately aware of the phenomenon of encountering your own code, and not understanding it. If it isn’t your own code, and it’s a departed team member, the situation can be even worse: it still doesn’t make sense, and the person who wrote it isn’t around to answer questions! Maintainable code becomes a prime concern after a short amount of time in an application, and this is no different with React applications.

Application structures

React is often referred to as simply “the view layer”. Most applications, whether web or anywhere else, follow a similar implementation pattern. There is code to produce data, to load it, to display it; the Model-View-Controller (MVC) pattern is common among many programming languages. Regardless of how it’s implemented, there is often a point in a software project where you have data that needs to be shown to a user.

Other web frameworks differ in complexity from React; Ember, for instance, provides the entire spectrum of tools needed for a web application. Version 1.0 included not just Handlebars templating for the view layer, but powerful controller and model tooling. The same story has applied to many web frameworks: it’s very easy to think of a web framework as incomplete if it doesn’t handle the entire end-to-end process of retrieving and displaying data.

React takes a different approach by firmly providing just views. Data can be passed in, sure, but React provides no built-in tooling for manipulating or loading data, besides what JavaScript itself contains. Want to load data? Check out Facebook’s GraphQL library, which has rethought the concept of retrieving data via REST. If your data is already defined and available, the popular Redux library can store your data and inject it into your React components.

(Be sure to check out our new Redux introduction series, too! Redux manufacturing)

I’ve referred to React’s ability to change how you write and think about code in every post in this series. React is a wonderful tool because it is obsessively simple. In being simple, it forces you to make changes to how you structure and reason about your application, and about the data that it needs. Redux is similar: data flows a single direction, so the way that you think about how data should move in your application will be permanently changed. In both these situations, is this the end-all, be-all, perfect solution to building applications? It’s hard to say–it does, however, paint an incredibly compelling and straightforward path to take in the future.

React components are functional by design–given input, we can always expect the same output from our render function:

output = render(input)

This line of code almost looks like an equation. Building out React component trees, like we did in the previous post in this series, is like combining many render equations into a single application:

header = render(title) + render(menu)

post = render(post_title) + render(post_date)
content = render(post) + render(post)

application = header + content

In building applications, React becomes somewhat of a game, as we explored with component trees: how modularized can we make this project? At what point does the application stop looking like a bundle of HTML, and more like a collection of highly-independent components?

Consider React Native, Facebook’s project to bring React to mobile devices. There are a number of stories of successful React Native launches targeting iOS and Android: most notably, Facebook’s own Ad Manager re-used 85% of component code between platforms. That insane level of re-use happens when we try and build maintainable, re-usable code; by building component trees that are highly modularized.

Structuring your React application can be as simple as a single flat directory of components. Our blog component tree from the last example might serve as a good reference:

Blog
  Header
    MenuItem
      Link
    MenuItem
      Link
  Posts
    Post
      PostDate
        SmallHeaderText
      PostTitle
        HeaderText
          Link
      PostContent
        Paragraph
          Link
        Paragraph
  Sidebar
    SmallHeader
      List
        Link
        Link
    SmallHeader
      List
        Link
  Footer
    Paragraph
      Link
    Paragraph
      Link

While there seem to be a number of highly-nested components in this structure, we can begin to see a more reasonable structure by flattening and removing duplicates:

Components/
  Blog.js
  Footer.js
  Header.js
  HeaderText.js
  Link.js
  List.js
  MenuItem.js
  Paragraph.js
  Post.js
  PostContent.js
  PostDate.js
  Posts.js
  PostTitle.js
  Sidebar.js
  SmallHeader.js
  SmallHeaderText.js

This list of components not only provides what we need for our blog application, but it can also provide components for other applications as well. I’ve seen many examples of multiple React applications re-using the same internal components–this provides consistency and rigor around how different teams or different projects are maintained by a larger organization. For instance, we might pull out the more general components not specific to the blog application, and package them as an internal “styleguide” for a company:

CompanyStyleguide/
  Components/
    Header.js
    HeaderText.js
    Link.js
    List.js
    Paragraph.js
    SmallHeader.js
    SmallHeaderText.js

In building this internal package, we could even begin to include more complex components, like Header, and extend or build off of them with custom solutions or by providing the ability to pass in options:

class BlogHeader extends React.Component {
  render() {
    return (
      // Component included from CompanyStyleguide package
      <Header backgroundColor="ffffff">
        <HeaderText color="000000" text="My Application" />
      </Header>
    )
  }
}

This is only scratching the surface of application structure in your projects. Again, we’re striving for maintainable, re-usable code: because React components are functional and straightforward, they lend themselves towards building these kind of modularized projects.

Open-source libraries

But what does this look like in practice, in a real React application? To explore this, we can turn to the wonderful world of open-source. There are a massive number of open-source components for React out in the world, and some of the most popular ones will exemplify good design by nature of being in use by huge numbers of developers and applications.

Some of the most popular open-source React projects repurpose existing design frameworks as React components. The material-ui project is one of these: with over twenty five thousand GitHub stars at time of writing, it’s clear that it’s an incredibly popular project in use by many applications.

Structurally, it looks like you might expect. A src folder designates the location of components, and each component is laid out in its own directory with optional tests (a topic we’ll cover in the next post):

material-ui/
  src/
    Checkbox/
      Checkbox.js
      Checkbox.spec.js
      index.js

The Checkbox component itself is fairly straightforward, with the exception of the number of options that can be passed in via props. Positions, styles, and behaviors are all customizable, and the component’s propTypes definition, a topic we covered in the previous post, is a good introduction into how you might override some of the component’s default behavior.

Interestingly enough, the Checkbox component’s render function reveals that the component does not return plain HTML. Like the best React projects, material-ui abstracts and modularizes the component, using the subcomponent EnhancedSwitch:

class Checkbox extends React.Component {
  render() {
    return (
      <EnhancedSwitch
        {...other}
        {...enhancedSwitchProps}
      />
    )
  }
}

The EnhancedSwitch component is stored in an internal directory, which handles the actual HTML rendering of components. In the render method of the EnhancedSwitch component, a collection of inputs, labels, and event handlers are collated into a single wrapped div:

class EnhancedSwitch extends React.Component {
  render() {
    return (
      <div ref="root" className={className} style={prepareStyles(Object.assign(styles.root, style))}>
        <EventListener
          target="window"
          onKeyDown={this.handleKeyDown}
          onKeyUp={this.handleKeyUp}
        />
        {inputElement}
        {elementsInOrder}
      </div>
    )
  }
}

We can see that in popular, highly-used React projects like material-ui, this modularized method of development highly lends itself to abstraction. It’s a practice that might seem unnecessarily verbose at first, but as projects grow in scale, it will continue to pay off dividends.

material-ui is just one of many incredibly useful React open-source libraries. The following are a couple of wonderful projects, that I can vouch for personally saving me time and frustration in my React applications. You should check them out not only to save you from duplicating functionality that has been battle tested by other users, but also to see what highly functional React components look like out in the world.

  • react-select: this project takes some of the best features of powerful JS select libraries and modernizes them as a powerful React component. I’ve used this library in almost every React application I’ve built–the onChange handler behavior and built-in support for multiselect, searching, and async tooling make react-select a first-class solution worth dropping into any project.
  • redux-form: well-behaved forms are deceptively hard to implement in React. While HTML5 has introduced a number of great behaviors for inputs, from requirement (this field must be filled out) to “type-checking” (this field can only be a number), support is browser-specific and may need to be more complex. redux-form does all of this and more, allowing form data to be passed through and handled by redux and wrapping form submission behavior in smarter, safer tooling. redux-form has a bit of a learning curve, but it has the ability to handle almost any form situation you throw at it. I’ve built a number of complex forms with redux-form, and found that even the basic functionality is so much better than the simple implementation I would have tried to ship an application with–it’s worth taking a look at, even just to consider what things you might have forgotten to include in your form code.
  • react-dnd: I wish that this stood for Dungeons and Dragons, but drag-and-drop functionality is cool too. Drag-and-drop is an interesting example of a JS feature that can break how you reason about your code: it’s so platform-specific and is firmly in the territory of jQuery and DOM-based libraries that including it into a React application can make components do a lot more than they really should. As a rule of thumb, when you begin to put jQuery functions in a componentDidMount hook, you should explore new approaches to that problem. react-dnd handles this as most advanced React components do: your original component becomes wrapped in a “higher-order component”: a component that returns another component. This familiar pattern often takes the form of a specific library function that returns your wrapped component–in react-dnd, this looks like connectDragSource(<YourComponent />). react-dnd is a glimpse at how interactive JS applications can still be written in a functional, performant way, without scattering jQuery handlers haphazardly through your application.

Programmers famously are lazy. We often say “Don’t Repeat Yourself”, and that code duplication is a “code smell”, and a sign of danger. This ethos has been only bolstered by the availability of high-quality open-source libraries.

You might be a really confident programmer and decide that writing your own datepicker component is a good usage of your time. As you begin to test it in different browsers (you are doing that, right?) you’ll quickly find that the CSS solution you had in mind probably doesn’t scale. Have you checked it out on mobile? Uh oh. These kind of concerns are handled when you use a project like react-dates: battle-tested not just by Airbnb, but developed with over fifty contributors coming from a variety of backgrounds and applications.

Want to receive this course in your email inbox? Join the A year with React.js mailing list–it’s instant and easy.

Bytesized offers technical training for companies. Contact us to schedule React.js training for your team today.

One week with React

This is part two in Bytesized’s A year with React.js series, which explores increasingly complex aspects of being a React developer. This post covers your first week with React––component lifecycle methods, and writing effective, re-usable components. It’s strongly recommended that readers start this series from the beginning: read the first post, “One hour with React”, here.

React components can often be thought of as being as simple as their input. In the previous post in this series, the NameComponent, a component defined with a single name prop, was pretty straightforward. What happens when the data being passed into a component is more complex? What about components that render other components? These patterns fall into intermediate to advanced React usage, and it’s in this area that many new React developers tend to become confused. If you’ve ever written a React component that should update as props change, but find that the component sits there doing nothing, this is the post for you.

In this post, we’ll cover more complex component trees, such as components that render other components. We’ll also explore React’s “prop types” feature, which leads to more correct and safe code. Finally, we’ll explore component lifecycle methods–knowing when and how a component is updating, and some common gotchas run into by new React developers.

Complex component trees

In the previous post in this series, I mentioned the “rewiring” that React does to your brain:

As you write more React code, you’ll find that it’s easiest to think in components: it’s an Arrival-esque “rewiring” of your brain, where you begin to internally modularize your planned code by default.

Larger React applications contribute to this behavior even more strongly–over time, a “tree” of components, that is, components with children components, becomes a familiar and even desirable structure for React developers to build. Take, for instance, this website:

While it’s a fairly simple design, there are a number of discrete elements on the page. We can break them down into components thusly:

These components represent large portions of the website’s design. We can imagine that each of these sections would also contain smaller components–for instance, a singular Post component may be comprised of additional, smaller components:

This can proceed ad-nauseum, until you’re completely exhausted by the number of components in your directory structure. It seems silly, but consider the advantages from a design and development perspective: a Text component can be used both by the Post component, and by any other place where paragraph-level text is required.

This practice is out there in the wild, used by high-functioning React.js development teams. Take react-bootstrap, for instance, a popular open-source React component wrapper around the Twitter Bootstrap framework. The Button component implements a component that simplifies generating different button types:

<Button>Default</Button>
// <button class="btn btn-default">Default</button>

<Button bsStyle="success">Successful action</Button>
// <button class="btn btn-success">Successful action</button>

<Button bsStyle="danger">Dangerous action</Button>
// <button class="btn btn-danger">Dangerous action</button>

By abstracting components out, application structure changes from a mess of inconsistent HTML to a consistent set of familiar patterns. Consider the following pseudo-trees for a Bytesized blog post, the first as a HTML, and the second as React components:

HTML:

div.post
  h2
    (Post date)
  h1
    (Post title)
  div.content
    p
      a
    p

React:

Post
  PostDate
    SmallHeaderText
  PostTitle
    HeaderText
  PostContent
    Paragraph
      Link
    Paragraph

Given these two trees, it may not be clear why the second is considered more ideal. Imagine a scenario where a designer on your team sends you a feature request: “Add the letter-spacing css class to all anchor/link tags”. In the HTML tree, this might be as simple as a find-and-replace. In the React tree, it’s simple too–after all, there’s only one Link component in our two paragraph post. We might do something like this to our Link component.

class Link extends React.Component {
  render() {
    return (
      // old
      // <a href={this.props.url}>{this.props.text}</a>

      // new
      <a className="letter-spacing" href={this.props.url}>{this.props.text}</a>
    )
  }
}

The advantages become clear when the second tree is viewed as a subsection of the larger blog tree:

Blog
  Header
    MenuItem
      Link
    MenuItem
      Link
  Posts
    Post
      PostDate
        SmallHeaderText
      PostTitle
        HeaderText
          Link
      PostContent
        Paragraph
          Link
        Paragraph
  Sidebar
    SmallHeader
      List
        Link
        Link
    SmallHeader
      List
        Link
  Footer
    Paragraph
      Link
    Paragraph
      Link

With a large number of links (nine in this tree, and likely to grow with time), used in a variety of places around the blog, it becomes a losing battle to do find-and-replace in an HTML-based component tree for this blog. Updating a single React component means that the change is propagated to every possible Link in the blog. This is a great example of why developers who have been writing React for a while proudly exclaim:

Prop Types

JavaScript is pretty well-known as a haphazard language. That’s pretty generous–it’s very easy to write JS code that doesn’t work. Gary Bernhardt’s well-known “Wat” lightning talk is a great demo of all the bad ways that JavaScript handles your code. The maintainers behind React are aware of this: with the project being actively used on the most popular website in the world, any and all additions to the project to bring a level of safety and rigor to JS should be considered a win.

Enter propTypes. React’s propTypes functionality provides validation around what props components should accept: given NameComponent, with a name prop, what should the passed-in name be? A number? An object? Most likely, it should be a string; propTypes allows you to check this:

class NameComponent extends React.Component {
  render() {
    return ( <h1>Hello, {this.props.name}!</h1> )
  }
}

NameComponent.propTypes = {
  name: PropTypes.string
}

Given this definition, we can explore what errors we’ll see in the console given bad input:

<NameComponent name={3} />

// Console output:
// Warning: Failed prop type: Invalid prop `name` of type `number` supplied to `NameComponent`, expected `string`.
//    in NameComponent

propTypes also can be used to notate when a prop is required:

NameComponent.propTypes = {
  name: PropTypes.string.isRequired
}

<NameComponent />

// Console output:
// Warning: Failed prop type: The prop `name` is marked as required in `NameComponent`, but its value is `undefined`.
//    in NameComponent

A particularly neat propTypes function is shape, which validates not only that a prop is an object, but allows nested validation for attributes inside the object:

NameComponent.propTypes = {
  name: React.PropTypes.shape({
    firstName: React.PropTypes.string
  })
}

const myName = { firstName: 3 }

<NameComponent name={myName} />

// Console output:
// Warning: Failed prop type: Invalid prop `name.firstName` of type `number` supplied to `NameComponent`, expected `string`.
//    in NameComponent

There are a number of useful functions as part of React’s propTypes library: from simple object/class validation to oneOf, an enum-check, and entirely custom validations, via passed-in functions. I highly encourage you check out the documentation: I have it bookmarked for quick reference as I write components.

React Component Lifecycle

React components have a number of “lifecycle” methods that can be hooked into by developers. These methods will be executed throughout the component’s normal operation. Some methods, like componentWillMount, happen before the component actually appears in the application. Others, like componentWillUnmount, happen right before a component is removed from the application. There is a variety of places to “plug in” with your application logic, and reading the “Component Lifecycle” section of the React component documentation will give you a better sense of where best to implement your application logic. Let’s look at a couple of examples of lifecycle methods in action.

There are some actions that need to happen with a component after it’s loaded. A common one is loading data via JSON. In the below example, we’ll display the current weather in San Diego, California, hooking into the componentDidMount method to fire a JSON request after the component is already displayed on the screen. You should notice brief (loading...) text before the temp state value is updated with the current temperature.

componentDidMount is commonly where XHR requests and other “preparatory” actions happen for a component. Initializing component-level validations, setting timers; things like this can’t happen when the component doesn’t yet exist, but if they happen too late (via a timer or another buggy solution), they may be inaccurate or out-of-sync with the component itself.

If you’re using jQuery or other DOM-level JS libraries, you’ll need to attach and detach handlers from your React components. Many developers will attach handlers to their components, but when the component disappears, they forget to detach the handlers–this often leads to messy consoles and, sometimes, complete application failure. componentWillUnmount is the place to do this: it allows one last place to perform logic before the component is destroyed by React’s DOM manager. In this simple example, we detach any jQuery events from our React component’s internal myElement, which is targetable using the ref prop:

Without the componentWillUnmount, we’ll leave a click event hanging until the page is either closed or refreshed. This isn’t a particularly egregious example of improper event handling, but without diligence, this kind of code can spiral out of control and lead to awful debugging sessions.

The props-related component lifecycle methods often are related to your component’s state: the default behavior usually works for most components, but if you find yourself having issues with components updating (or not updating) as new props are passed in, you may want to take a look at componentWillReceiveProps and shouldComponentUpdate:

componentWillReceiveProps(nextProps) {
  // compare the old props to the new props:
  if (this.props != nextProps) {
    // act on new props, for example
    this.setState({ temp: nextProps.temp })
  }
}

shouldComponentUpdate(nextProps, nextState) {
  // Force the component to update and re-render
  // if the new props or state are different

  // For instance, re-render if the `temp` value in
  // the new state has been changed
  return nextState.temp != this.state.temp
}

shouldComponentUpdate is a particularly interesting method that can be used to optimize components: by default, React components re-render on every state change. React is incredibly efficient and this behavior usually does not lead to performance issues, but if you have slow components, you might want to re-visit and strictly determine when your components re-render.

Component lifecycle methods can be tricky to wrap your head around, and they often are a good first stop in debugging your components if you find they aren’t behaving as expected. The mental model of a React developer is pretty straightforward: data usually flows one direction–down and through components–and it’s usually obvious how and when a component will render. If you find that to not be the case, define lifecycle methods for your component, and at the least, try inspecting the props and state being passed through via console.log.

Want to receive this course in your email inbox? Join the A year with React.js mailing list–it’s instant and easy.

Bytesized offers technical training for companies. Contact us to schedule React.js training for your team today.

One hour with React

Welcome to the first post in Bytesized’s free course “A year with React.js”. In this series, we’ll explore the React JavaScript framework, beginning with the concepts you need to know for your first hour with the framework. In later parts of the series, we’ll touch on increasingly complex aspects of being a React developer. As you might expect, the concepts and “gotchas” worth exploring after working with the framework for an hour, one week or one month differ greatly. This post covers your first hour with React––initializing components, and providing data via props and state.

React components are the building blocks of a React.js application. As you write more React code, you’ll find that it’s easiest to think in components: it’s an Arrival-esque “rewiring” of your brain, where you begin to internally modularize your planned code by default.

A React component is simply a JavaScript function that ultimately renders to the DOM. In React.js, this means rendering HTML; in React Native, this could mean rendering to the iOS or Android viewport. Note that the rendering component is not strictly defined––this is an advantage of the platform. React intentionally separates this part of the process from writing actual React components, which allows React to be used to build a variety of interfaces that aren’t necessarily web-related, like VR apps.

Depending on your toolchain, you may use Facebook’s JSX tool to write HTML-like code inside your JavaScript, or forego it for entirely JS-based functions. For most React components using JSX and ES6, a simple React component looks like this:

This simple React component returns an HTML div container, with a primary header of “Hello, world!”. This is a “static” component––it doesn’t take any input and doesn’t perform any updates. In another post, we’ll explore how React components update via lifecycle methods; for now, let’s look at providing “input” and building more dynamic components.

In examining React components, it can be useful to separate the important facets of it into internal and external categories—for instance, what can be passed in to a component, and what can a component manage itself? Let’s begin with external, and see how initializing a React component can work.

External to the component

Given what we currently know about components, we would be unable to define a NameComponent that returns “Hello, (name)”. The name variable must be passed into the component, and the component must store some kind of “state”.

React components accept external properties in the form of “props”. Props can be of any form—however, most developers will insist on keeping their props as simple JS types: strings, numbers, arrays, and objects. Initializing a component with a name prop takes the form of:

<NameComponent name="Kristian" />

Given the name prop, we can render it in the component using this.props:

Any number of NameComponent components can be defined, each with a different name. Each component operates independently, because the name prop has been provided with an entirely different value.

Internal to the component

Components can also internally store state. Instead of passing in a name prop, we can set an initial state and use it to display a name:

Given this definition, no props are required to initialize the component. In fact, doing so will be useless, as the prop would never be used.

By using a React component’s internal state, we can provide simple “dynamic” functionality, and update a name value––for instance, by clicking a button:

The updateName method, which fires when the button element is clicked, changes the internal state to have a name value of “George”. Again, each React component has independent state, so initializing multiple components means that each button can be used to update state separately.

All React components are, fundamentally, a combination of structure (JSX logic) and input (props and state), with the ultimate goal of rendered output (HTML, React Native views, etc). As you move into more complicated React components, the way that these pieces fit together may change slightly: the popular Redux data library, for instance, foregoes component state entirely, preferring to store application state at the global level and passing information only as props.

Intermediate and advanced components may substitute rendering HTML for rendering more components: a Header component, for instance, could be comprised of various MenuItem components, as opposed to raw li elements or something similar.

Want to receive this course in your email inbox? Join the A year with React.js mailing list–it’s instant and easy.

Bytesized offers technical training for companies. Contact us to schedule React.js training for your team today.