React

The purpose of this document is to help guide you through working with a potential project using the JavaScript library, React. Outside of the official React documentation, you should find here personalized recommendations for using the library based on the types of projects we typically see at 10up. We have broken these recommendations out into common elements we tend to interact with often in client work. If something you’re looking for isn’t represented you can either submit a pull request to this repository or refer to the official React documentation.

Figuring Out If React Is Right For Your Project

Using the right tool for the job is critical in navigating a successful project. Will React always be the answer? Of course not. But there are some instances where you may want to use this library over something like (for example) a collection of plugins, custom JavaScript, or another framework.

When deciding whether React is the right tool for your project, it might help to ask the following questions:

React is easily integrated into specific parts of the front-end or admin of an existing site, but it can also be used to render entire sites, effectively replacing traditional WordPress templates—although doing so requires a lot more planning and scaffolding of features (such as routing) that would normally be handled by the CMS out of the box.

Components

When building out components, it’s beneficial to understand how to construct them in the most appropriate way possible. Certain “types” of components can be written differently which can have big performance benefits on larger scale applications.

Class Components

Class Components are written in the ES6 Class syntax. When building a component using a JS Class, you are generally inferring that the component either manages it’s own state or it’s state is managed by a state management library like Redux.

Class components are also capabale of handling props. Use these components when you need to build “intelligent” React components that are aware of their own state as well as the state of their children.

Stateless Functions

A Stateless function can take the form of a plain function in JavaScript, or a fat arrow function stored in a variable. The biggest difference between a Class Component and a Stateless Function is that Stateless Functions are not aware of state. state can not be passed to them from a parent (unless it’s through props) thus the component cannot update state. Stateless Function’s can handle props as a destructured object as a parameter.

If your component is not required to update state or the state of child components use a Stateless Function. They have a low re-render cost and provide for cleaner code.

PureComponents

PureComponents allow for greater performance benefits with in the React Lifecycle. When using a Pure Component, the logic of the shouldComponentUpdate lifecycle method is altered to perform a shallow comparison of what changed in props and state since the last render.

Considering PureComponents perform shallow comparisons of previous state and new state, a component should become “pure” when theres no need to re-render the entire component (or its children) every time data changes. You can also use PureComponents if you’re building a stateless component, but still need lifecycle methods. Examples would include: TodoLists, Star Ratings, Event Calendars, Forms, Comments

NOTE: The performance benefits are realized when the data passed to the component is simple. Large nested objects, and complex arrays passed to PureComponents may end up degrading the performance benefits. It’s important to be very deliberate about your use of this type of component.

Routing

In most cases, you will only need routing if your React application needs to navigate between multiple layout components, render different data based on the current app location, and provide browser history. Make sure your app needs routing functionality before you consider adding a routing library.

React Router

The most popular routing library for React is React Router. React Router provides a core library plus APIs for both DOM (web) and React Native (native iOS and Android) platforms. To use the library, install the package for one or the other API according to your application’s platform needs—the core library is included in both.

To read more about the concept of dynamic routing, with plenty of code examples to follow along with, refer to the React Router documentation.

Routing Accessibility

In general, routing is little more than an Ajax call to load content with a URL update. This pattern poses some accessibility problems since there is no true page reload. To overcome this and make sure our React implementations pass accessibility compliance we need to ensure a few things happen:

  1. Update the page title.
  2. Programmatically reassign focus with a ref to the new loaded content.
  3. Alert the user of any changes (like a new page loading).

Following these steps will make sure your content and routing is readable by assistive technology.

Props and State

State in React is the lifeblood of the component. State determines how, and with what data, a component will be rendered on the page. State gives components reactivity and dynamic rendering abilities.

Props serve as a means to pass data between components. At its most basic level, props are passed to each individual component that needs to consume and utilize that data. Basic applications will likely be able to pass data using this default behavior.

As an application becomes more complex, it may become more of a hassle to pass data down to many child components. This is where frameworks like Redux will come in. However before you reach for these third party frameworks, consider the React Context API

Context API

The React Context API is the first line of defense when your application becomes sufficiently complex, and we are faced with prop drilling concerns.

Context provides a way to pass data through the component tree without having to pass props down manually at every level. This is immensely helpful for applications that are highly componentized, and need to share data with those components, regardless of where they exist within the application structure. It is crucial that you think critically about how the data in your application is to be utilized and passed around. If data simply needs to be shared, Context may be for you.

Context does not however provide the further sophisticated features of libraries like Redux. Stepping through application history, alternate UIs that reuse business logic, state changes based on actions etc. If those are things that you need in your application, the Context API may not be quite robust enough for you.

Redux

As an application grows larger, it may be the case where the state becomes difficult to handle, every new feature introduces a new layer of complexity that may in some cases result in unexpected, and unpredictable behavior.

Redux is a state container that stops the ever-changing nature of the state itself. It acts as a protector of the state, allowing only certain defined actions to trigger a state update. Thus making it predictable.

Principles of Redux

Redux is based almost completely on 3 main principles:

  1. Single Source of Truth: This is a main tree object which holds the entire state of your application. It’s meant to help your application to be seen as a whole.
  2. State is Read Only: The state of the application stops being mutable, the only way to change the state is by triggering an action, which itself will work as a log of what, when, and why changed in the state.
  3. Changes are made with pure functions: This means that only an action (or an event) can trigger a Reducer which will take the previous state and return a new one.

When to use Redux

As appealing as it might be. Redux is not a tool for everyday use. By design, Redux will put constraints in your application that may not actually be needed. A good starting point to make this choice is the article by its creator, Dan Abramov: You might not need Redux. The usual recommendation is, think in React. And if along the way you discover the need of Redux, implement it.

Accessibility

React accessibility is not so different than standard accessibility support. It mainly centers around making sure semantic HTML and proper attributes are used with the correct elements. Managing focus flow and repairing when necessary. Be sure to also use the jsx-a11y eslint plugin to ensure your code maintains a solid accessible foundation.

Semantic HTML and Fragments

Using the the most relevant HTML elements is always preferred, and doesn’t change when using React. Sometimes we can break HTML semantics when we add div elements to our JSX to make our React code work, especially with a set of elements such as lists. In these cases we should use Fragments.

Fragments are a pattern used in React which allow a component to return multiple elements, without an encompassing div component. Using div elements in certain contexts may break HTML semantics. Use fragment when a key prop is required Use <elem></elem> syntax everywhere else

Accessible Forms

Standard HTML practices should be used for forms. One caveat though is making sure all inputs have proper labeling. In React the “for” attribute is written as “htmlFor” in JSX.

<label htmlFor="namedInput">Name:</label>
<input id="namedInput" type="text" name="name"/>

Programmatically managing focus

React applications continuously modify the HTML DOM during runtime, sometimes leading to keyboard focus being lost or set to an unexpected element. React provides “Refs” in order to modify child components or elements outside of the standard flow. These can help us specifically manage keyboard focus.

The ref attribute can be placed on any React component, with a function value. This function will be executed as soon as the component is mounted or unmounted. The first parameter of the function will be a reference to the element or the component the ref is on.

Read more about creating refs and focus control in React

Server Side Rendering

With server side rendering (SSR), the initial content is generated on the server, so your browser can download a page with HTML content already in place. Updates to the content are still handled in the browser.

Here are three topics to consider when looking at server-side rendering:

When to Use Server-side Rendering

Other things to consider when using SSR:

Prerendering

If you’re only investigating SSR to improve the SEO of a handful of marketing pages, you probably want prerendering instead. Rather than using a web server to compile HTML on-the-fly, prerendering simply generates static HTML files for specific routes at build time. The advantage is setting up prerendering is much simpler and allows you to keep your frontend as a fully static site.

Debugging

React provides a Chrome & Firefox extension to facilitate debugging. It is an extremely useful debugging tool, providing quick transparent access into the data within your React instance. Whenever you encounter a new concept in React, it’s generally a good idea to open up the dev tool, and observe your application state.

Gutenberg

When creating Gutenberg components in the WordPress editor, mostly you’ll find yourself adhering to the standard best practices of React, but there are a few Gutenberg-specific design patterns you should be aware of before starting a new build.

@wordpress/element

Element is an abstraction layer atop React created just for WordPress and used within Gutenberg components. It was created to allow engineers an API entry point into Gutenberg with deliberate features, omissions, and protections from core-library updates (React updates, in this case) that could cause breaking changes in an interface.

The presence of Element is why you don’t see React directly imported into Gutenberg components. Read more about using Element in Gutenberg.

Higher-order Components

Gutenberg offers a library of higher-order components (HOC) you can use to build out a robust editor experience. The features of these components range from focus management to auditory messaging. It is best to familiarize yourself with these components so you don’t end up rebuilding a utility functionality that already exists within Gutenberg. You can view Gutenberg’s library of generic Higher Order React Components to learn more or view the official React documentation for general information about using HOC.

As with any evolving feature, it is important to frequently check the documentation for new additions and updates.