20 Essential React Tools for 2020

The React ecosystem has evolved into a growing list of dev tools and libraries. The plethora of tools is a true testament to its popularity. For devs, it can be a dizzying exercise to navigate this maze that changes at neck-breaking speed. To help navigate your course, below is a list of essential React tools for 2020.

Hooks

Hooks are a new addition to React as of version 16.8. They unlock useful features in classless components. With Hooks, React no longer needs lifecycle methods such as componentDidMount to manage state. This encourages separation of concerns because components are not managing their own state. Putting a lot of state management inside class components blows up complexity. This makes stateful components harder to maintain. Hooks attempt to alleviate this problem by providing key features.

The following basic Hooks are available:

  • useState: for mutating state in a classless component without lifecycle methods
  • useEffect: for executing functions post-render, useful for firing Ajax requests
  • useContext: for switching component context data, even outside component props

Pros:

  • mitigates state management complexity
  • supports functional components
  • encourages separation of concerns

Cons:

  • context data switching can exponentiate cognitive load

Functional Components

Functional components are a declarative way to create JSX markup without class components. They embrace the functional paradigm because they don’t manage state in lifecycle methods. This emphasizes focus on the UI markup without much logic. Because the component relies on props it becomes easier to test. Props have a one-to-one relationship with the rendered output.

This is what a functional component looks like in React:

const SimpleComponent = ({isInit, data}) =>
<>
  {useEffect(() => {!isInt && loadAjaxData()})}
  {data}
</>

Pros:

  • focuses on the UI only
  • testable component
  • less cognitive load when thinking about the component

Cons:

  • no lifecycle methods

Create React App

The quintessential tool to fire up a new React project. This manages all React dependencies via a single npm package. No more dealing with Babel, webpack, and whatnot. The entire dependency tool chain gets upgraded with react-scripts in package.json. There’s a way to integrate Create React App with any server-side rendering tool out there. The tool outputs index.html and static assets in the public folder. This public folder is the touch point where static assets are ready for integration.

It’s easy to get started:

npx create-react-app my-killer-app

And it’s even easier to upgrade later:

npm i react-scripts@latest

Pros:

  • easy to get started
  • easy to upgrade
  • single meta-dependency

Cons:

  • no server-side rendering, but allows for integration

Proxy Server

Starting from version react-scripts@0.2.3 or higher, it’s possible to proxy API requests. This allows the back-end API and local Create React App project to co-exist. From the client side, making a request to /my-killer-api/get-data routes the request through the proxy server. This seamless integration works both in local dev and post-build. If local dev runs on port localhost:3000, then API requests go through the proxy server. Once you deploy static assets, then it goes through whatever back end hosts these assets.

To set a proxy server in package.json:

"proxy": "http://localhost/my-killer-api-base-url"

If the back-end API is hosted with a relative path, set the home page:

"homepage": "/relative-path"

Pros:

  • seamless integration with back-end API
  • eliminates CORS issues
  • easy set up

Con

  • might need a server-side proxy layer with multiple APIs

PropTypes

Declares the type intended for the React component and documents its intent. This shows a warning in local dev if the types don’t match. It supports all JavaScript primitives such as bool, number, and string. It can document which props are required via isRequired.

For example:

import PropTypes;

MyComponent.propTypes = {
  boolProperty: PropTypes.bool,
  numberProperty: PropTypes.number,
  requiredProperty: PropTypes.string.isRequired
};

Pros:

  • documents component’s intent
  • shows warnings in local dev
  • supports all JavaScript primitives

Cons:

  • no compile type checking

TypeScript

JavaScript that scales for React projects with compile type checking. This supports all React libraries and tools with type declarations. It’s a superset of JavaScript, so it’s possible to opt out of the type checker. This both documents intent and fails the build when it doesn’t match. In Create React App projects, turn it on by passing in --template typescript. TypeScript support is available starting from version react-script@2.1.0.

To declare a prop type:

interface MyComponentProps {
  boolProp?: boolean; // optional
  numberProp?: number; // optional
  requiredProp: string;
}

Pros:

  • compile type checking
  • supports all React tools and libraries, including Create React App
  • nice way to up your JavaScript skills

Cons:

  • has a learning curve, but opt out is possible

Redux

Predictable state management container for JavaScript apps. This tool comes with a store that manages state data. State mutation is only possible via a dispatch message. The message object contains a type that signals to the reducer which mutation to fire. The recommendation is to keep everything in the app in a single store. Redux supports multiple reducers in a single store. Reducers have a one-to-one relationship between input parameters and output state. This makes reducers pure functions.

A typical reducer that mutates state might look like this:

const simpleReducer = (state = {}, action) => {
  switch (action.type) {
    case 'SIMPLE_UPDATE_DATA':
      return {...state, data: action.payload};

    default:
      return state;
  }
};

Pros:

  • predictable state management
  • multiple reducers in a single store
  • reducers are pure functions

Cons:

  • set up from scratch can be a bit painful

React-Redux

Official React bindings for Redux, it comes in two main modules: Provider and connect. The Provider is a React component with a store prop. This prop is how a single store hooks up to the JSX markup. The connect function takes in two parameters: mapStateToProps, and mapDispatchToProps. This is where state management from Redux ties into component props. As state mutates, or dispatches fire, bindings take care of setting state in React.

This is how a connect might look:

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

const mapStateToProps = (state) => state.simple;
const mapDispatchToProps = (dispatch) =>
  bindActionCreators({() => ({type: 'SIMPLE_UPDATE_DATA'})}, dispatch);

connect(mapStateToProps, mapDispatchToProps)(SimpleComponent);

Pros:

  • official React bindings for Redux
  • binds with JSX markup
  • connects components to a single store

Cons:

  • learning curve is somewhat steep

Redux-Thunk

Thunk middleware for Redux to make asynchronous API calls. It defers execution behind a thunk to unlock asynchrony. A thunk is a function that defers evaluation. For example, () => 1 + 1, because it doesn’t have immediate execution. This comes with niceties, like access to store state, and dispatch. Optional parameters are also supported in the thunk.

For example:

const loadData = () => async (dispatch, getState, optionalAsyncTool) => {
  const state = getState();

  const response = await optionalAsyncTool.get('/url/' + state.data);
  dispatch({type: 'SIMPLE_LOAD_DATA', payload: response.data});
};

Pros:

  • quintessential tool for asynchrony
  • access to state, and dispatch
  • configurable with optional parameter

Cons:

  • at first, usefulness is not super clear

Redux-Logger

Logger for Redux that captures any dispatches going through the store. Each dispatch shows in the dev console in a log message. It allows drilling into prev, and next state. The action in the dispatch is also available for payload inspection. This logger is useful in local dev and can be ripped out post-build.

The following is a potential setup in Redux middleware:

import { createStore } from 'redux';

let middleware = [];

if (process.env.NODE_ENV === 'development') { // rip out post-build
  const {logger} = require('redux-logger');
  middleware.push(logger);
}

export default () => createStore({}, applyMiddleware(...middleware));

Pros:

  • good Redux insight
  • captures all dispatches in the store
  • can run in local dev only

Cons:

  • tricky to filter out unwanted messages

Lodash

A modern JavaScript utility library useful for React components. React form input evens like onChange fire once per keystroke. If the component gets data from a back-end API, it fires requests once per keystroke. This spams the back-end API and causes issues when many people use the UI. Lodash comes with debounced events, which fires one API request with many keystrokes.

To set up onChange debounced events:

onChange={(e) => debounce(updateDataValue(e.target.value), 250)}

Pros:

  • modular dependency
  • plays well with code-splitting
  • easy to use

Cons:

  • knowing when to debounce events is not immediately obvious

Axios

Promise-based HTTP client that works well in thunks. The tool supports async/await syntax to make Ajax requests from the browser. It supports error handling in case there are errors via catch. The tool’s API supports HTTP requests such as GET, DELETE, POST, PUT, and PATCH. This also plays well with Promise API calls like Promise.all() to send HTTP requests in parallel.

From inside a thunk, axios can work like this:

const loadData = () => async (dispatch, getState, axios) => {
  try {
    const response = await Promise.all([
      axios.get('/url'),
      axios.post('/url', getState())
    ]);

    dispatch(updateData(response[0].data));
    return dispatch(updateData(response[1].data));
  } catch (reason) {
    return dispatch(error(reason.message));
  }
};

Pros:

  • promise based
  • supports async/await
  • supports error handling

Cons:

  • it can’t get any more awesome

Jest

Jest is a testing framework with a focus on simplicity for JavaScript projects. The good news is it comes built-in with Create React App. It works with projects that use Babel, TypeScript, and Node. There’s no configuration on most React projects. Tests can run in watch mode, which keeps track of code changes and reruns tests. The API contains it, and expect to quickly get started.

A sanity check to make sure tests execute is:

it('says true is true', () => {
  expect(true).toBe(true);
});

Pros:

  • easy set up with Create React App
  • fluent API
  • runs in watch mode

Cons:

  • too bare bones to render React components

Enzyme

A JavaScript testing utility for React that makes it easier to test components. The API is meant to be as intuitive as jQuery for component traversal. To get Enzyme, it needs two packages: enzyme, and a separate adapter. The adapter must be compatible with the version of React. For example, enzyme-adapter-react-16 for React ^16.4.0, enzyme-adapter-react-16.3 for ~16.3.0, so on and so forth. The adapter needs a configuration file setupTest.js to integrate with Jest.

When using React 16, install Enzyme with:

npm i --save-dev enzyme enzyme-adapter-react-16

Pros:

  • supports React components
  • supports Jest test framework
  • intuitive API

Cons:

  • kind of painful to set up adapter in Jest

Shallow Renderer

This is shallow rendering useful for limiting tests to one level deep. It renders the parent component without affecting its children in a tree hierarchy. This isolates the test and makes assertions more robust. Shallow rendering supports a good chunk of the Enzyme API for traversing components. The shallow API does call lifecycle methods like componentDidMount and componentDidUpdate during render. With Hooks, the shallow renderer does not call useEffect. One tip is do console.log(component.debug()) to inspect what the shallow renderer sees.

To test a React component using the shallow renderer:

const component = shallow(<ParentComponent data={"Dave"} />);
expect(component.find('p').at(0).text()).toBe('Dave');

Pros:

  • isolates test
  • full featured API
  • allows quick debugging

Cons:

  • must navigate the sea of options in Enzyme’s API to find this diamond in the rough

Storybook

Open-source tool for manual testing of React components in isolation. Storybook provides a sandbox to build components to get into hard to reach edge cases. It allows mocking so it can render components in key states that are hard to reproduce. Setup is automatic with Create React App when using react-scripts. Each story in Storybook can target a single component with many states. The story files have a convention like component.stories.js so one can quickly find them.

To get started with Storybook:

npx -p @storybook/cli sb init

Pros:

  • covers hard to reach edge cases
  • renders components in sandbox
  • integrates with Create React App

Cons:

  • hard to automate tests

React Bootstrap

This is the most popular front-end framework rebuilt for React. Every Bootstrap component is built from scratch as a React component. This replaces Bootstrap JavaScript and nukes dependencies like jQuery. The latest beta version supports Bootstrap 4.3. React Bootstrap works with the thousands of Bootstrap themes already found in version 4. Each component has accessibility in mind and is accessible by default. It supports Create React App out of the box, and custom themes are also supported.

To fire up React Bootstrap in a React project:

npm install react-bootstrap bootstrap

This is what the result might look like:

React Bootstrap

Pros:

  • rebuilt from scratch with React components
  • accessibility in mind
  • supports Create React App

Cons:

  • custom themes can be tricky in Create React App

Material-UI

Popular React components for faster and easier web development. This allows building your own design system or starting with Material Design. There are templates and themes available, both premium and free. Premium themes have a price tag depending on functionality. Material-UI comes via an NPM package for quick installation.

To get started with Material-UI:

npm install @material-ui/core

This is what the result might look like:

Material-UI
Source

Pros:

  • build a powerful UI with less effort
  • offers many components
  • offers many templates

Cons:

  • some premium templates do cost, but might be worth the money

Elemental UI

A toolkit for React apps initially for use in KeystoneJS. It’s an experimental UI toolkit born out of real-world requirements. The goal is an unopinionated set of React components, as standalone or bundled together. It comes with an unobtrusive default style and flexible theme capabilities.

To get started with Elemental UI:

npm i elemental --save

The result might look like this:

Elemental UI

Pros:

  • reusable standalone components
  • flexible default styles
  • inspired by real world scenarios

Cons:

  • still in development

Semantic UI

The official Semantic UI React integration UI toolkit. Comes jQuery free because all jQuery functionality is re-built in React. A declarative API provides robust features and prop validation. Augmentation via as allows control of the output, useful for MenuLinks and react-router. Shorthand props generate markup, this makes use cases easier to work with. Subcomponents have complete access to the markup; this flexibility unlocks customizing components. Stateful components manage state out of the box, without extra wiring. For example, Dropdown opens on click without onClick to the open prop. Setting a prop delegates control to this prop value, while the rest remain auto controlled.

This is what augmentation in React Semantic UI might look like:

import { Link } from 'react-router-dom';

<Menu>
  <Menu.Item as={Link} to="/menu-item">
    Menu Item
  </Menu.Item>
</Menu>

And, this is the look and feel:

Semantic UI
Source

Pros:

  • jQuery free
  • declarative via props
  • augmentation allows plenty customization

Cons:

  • hard to come up with any

Conclusion

As shown, React’s ecosystem has exploded within the last few years. It’s the tool of choice for enterprise wanting to reuse React components in a consistent suite. Each tool is standalone with few interdependencies. For 2020, my recommendation is to give these tools at least a try.

In the meantime, build your React skills with our recommended further reading:

Comments are not currently available for this post.