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 XWP. 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 like Vue.

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

  • Will this project involve building a user interface that requires statefulness? In other words, will your user interface need to react in real time to user actions or changeable data coming from an API?

  • Does your project need enough reusable components to make it worth using React? React is a fairly heavy framework compared to something like Vue, which is similar but has different use cases and is more lightweight.

  • Will your project need to render large amounts of data in real time while remaining performant for the browser?

  • Are you building a native mobile app for iOS and/or Android? The React team also maintains React Native, a subset of React which makes it possible to write applications in JavaScript using React components that compile to native Swift and Java.

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 capable 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:

  • SEO: Rendering server-side helps search engine crawlers find your content, but sometimes Google can find your content without SSR.

  • Performance: SSR will usually increase performance for your app, but not always.

  • Complexity: Using SSR will increase the complexity of your application, which means less time working on other features and improvements.

When to Use Server-side Rendering

  • You need SEO on Google, DuckDuckGo, Bing, Yahoo, or Baidu and performing consistently across all of them. Note that as of now, Google and Bing can index synchronous JavaScript applications—synchronous being the key word. If your app starts with a loading spinner, then fetches content via Ajax, the crawler will only wait a few seconds for loading to complete. This means if you have content fetched asynchronously on pages where SEO is important, SSR might be necessary.

  • If you are looking for an alternative to improve user experience and performance. Server-rendered markup doesn’t need to wait until all JavaScript has been downloaded and executed to be displayed, so your user will see a fully-rendered page sooner. This generally results in better user experience, and can be critical for applications where time-to-content is directly associated with conversion rate.

Other things to consider when using SSR:

  • Issues might arise when using SSR with third-party libraries, which to render the components need to access certain variables that are only available in the browser (for e.g window, document…).

  • Rendering a full app in Node.js is obviously going to be more CPU-intensive than just serving static files, so if you expect high traffic, be prepared for corresponding server load and wisely employ caching strategies.

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.

Before starting from scratch you should probably use our block-extend plugin for projects that extend the Gutenberg editor.

@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.