. 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 Kanopi. 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
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:
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 library compared with the similar Vue.
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
Some components are naturally better suited for using class components. As an example consider the following component that consumes a stream of frames:
import React, { Component } from 'react';
class Camera extends Component {
handleCameraStream = (frames) => {
// this method has proper access to props and state. Even if Camera re-renders.
onReady is only called when the camera stream is ready and the handleCameraStream method sets up a loop, if Camera re-renders, onReady is not called again. If Camera was a functional component, everytime it re-rendered and its props/state changed, the handleCameraStream callback would not have the right scope to have access to the most up-to-date state/props as the function was bound to the first render. The alternative for using functional components is storing each frame in state through useState and process frames in a separate function but that adds complexity and unecessary re-renders every time a new frame is received.
in JavaScript, or a fat arrow function stored in a variable. In the past, the biggest difference between a Class Component and a Functional Component was that Functional Components were not aware of state. With the introduction of
functional components are now able to handle most of the React APIs such as state, contexts, refs and lifecycle.
Functional components are the recommended way to write React components as they come with less boilerplate code, allows you to reuse stateful logic without changing component hierarchy and complex components become easier to understand by avoiding a myriad of complex logic spread between componentDidUpdate, componentDidMount and other lifecycle class methods.
The following example is the previous SearchInput component converted to a functional component using hooks.
implements the shouldComponentUpdate lifecycle method 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.
Typically, you won’t need to create PureComponents as functional components and react hooks are better tools for the job. Do not use PureComponent if you are building stateless functional component and need lifecycle methods, use the useEffect hook instead.
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 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
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:
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.
State Management
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
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.
You also need to be careful with the fact that any component “connected” to a given React Context will re-render automatically when the data the context holds changes. There’s no built-in mechanism to mapStateToProps within the Context API. One way to solve this problem is to create multiple specialized contexts for you application that only stores a specific portion of you shared global state. For example, a “User” context that holds user data and a “Posts” context that holds a list of posts to be rendered on the application.
For example, consider the following UserProvider component that is responsible for fetching an user if it’s logged in and storing the user object in a React Context.
import React, { useEffect, useState, useContext, createContext } from 'react';
import PropTypes from 'prop-types';
import { fetchUser } from '../util';
export const UserContext = createContext();
export const useUser = () => {
const data = useContext(UserContext);
return data.user ? data.user : null;
};
const UserProvider = ({ children }) => {
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser().then(setUser);
}, []);
return <UserContext.Provider value={{ user }}>{children}</UserContext.Provider>;