This article was created in partnership with Sencha. Thank you for supporting the partners who make Zentica possible.
React is a collection of tools and libraries that are independent of each other, which can be daunting for React developers with a job to do. The many tools grants plenty of freedom because you can shop around for the best ones for the job at hand. In React, there are many ways to solve a problem so knowing more than a few tools is a good idea. There are tools that are better at certain problems than others, it all depends on the context. Below is a list of tools I find useful in a good sized React project, some are newer than others and some solve a specific problem when working with React – but all of them I’ve found helpful.
For each React tool, I’ll provide a short summary with basic information before diving a bit deeper with cool things it can do and my thoughts. Keep in mind all these tools are subject to change.
A great way to begin a React project is through Create React App. This tool abstracts much of the React tooling into a single dependency. Tools like Webpack, Babel, and ESList are safe under the hood. You can begin an entire React project with a single command. The tool generates a minimal set of files so you can focus on the app. You’ll need Node 6+ to use this.
For example, to fire up an app with
npx create-react-app my-killer-app
Running the command above will create a directory and generate scaffolding files. The command installs transitive dependencies without intervention. There are no complicated configuration files, only the bare minimum to build your app.
Upgrades get encapsulated by a single NPM package. No need to mess with webpack and friends to take advantage of the latest features. You can upgrade Create React App with a single command when new versions ship. To upgrade, install the
[email protected] NPM package.
Inside the project folder, you can find built-in commands. Running
npm start, for example, boots up the app. While running, the app hot loads any changes you make to the code. As you save project files it will reload these changes in the browser. Any compilation errors that occurs will show up in the console that ran the app.
Create React App has your back with test automation. Running
npm test will fire up Jest and run all tests in your project. The command runs a watcher in interactive mode, so it’ll keep track of file changes. As you make changes the watcher runs only the tests affected. Be sure to name test files
*.test.js so Jest can pick them up.
- begin with a single command
- only a single dependency
- no configuration necessary
Next.js does server-side rendering through an isomorphic React app. There is zero set up and takes little time to get started. You get code splitting, folder-based routing, hot code reloading, and universal rendering. Code splitting loads only the necessary components on the page. Routing looks for a
pages folder in the project and finds the file that matches the linked route. Hot code reloading watches for file changes and reloads parts of the app. This is nice for developers who like fast feedback loops between code changes. Rendering happens both on the client and the server because the app is isomorphic. This allows code reuse because the same code that runs on the server also runs on the client.
To get started with Next.js, do:
npm install --save next react react-dom
Make sure you create a project folder with a
package.json. In this package file, wire up Next.js with
next build, and
next start scripts. These scripts map to run scripts you execute through NPM.
With Next.js, you can host static files by creating a
static folder. Everything you place in this folder becomes a static asset in the app. This allows you to serve assets such as images or CSS.
You can export Next.js as static HTML pages to eliminate server-side rendering. In the project folder
next export generates static HTML pages you can host anywhere. Exporting supports almost every feature, dynamic URLs, prefetching, preloading, and dynamic imports. By default, there is no configuration necessary. It generates static HTML files from the
pages directory. The export command lives inside the
package.json, so run it with
npm run export. Export files will appear in the
- zero configuration with advanced features
- app is ready for prod with no hassle
- static HTML option eliminates server-side rendering
- customizing routes can be a hassle
In React, it is cumbersome to pass around many props and state parameters. A hierarchy of components can have many React components. A single parameter mishap somewhere along the chain is hazardous. This makes it frustrating to debug parameters when there are a lot of components.
<Provider /> makes the Redux store available to the root component. A
connect function maps states to props to all components in the store. The connect function feeds the parameters necessary for each component to work.
In a typical React app, there is a single root component with one store. There can be a hierarchy of Redux stores that split the state tree. This is like React where a single root component can have many small components.
To set up Redux bindings in a React project:
npm install --save redux react-redux
Be sure to treat Redux and React-Redux as separate dependencies.
- embraces sound programming like pure functions
- bindings are available for React
- automates state management
- set up from scratch can be a bit painful
Enzyme is like jQuery for testing React components. You can shallow render components without a headless browser. You can traverse, search for components, and make assertions. This shortens the feedback loop because it eliminates the browser. Shallow rendering is useful because it doesn’t go more than one level deep. This isolates the test to a single level in a hierarchy of React components.
Enzyme’s API supports event simulation. The
simulate() function calls the event handler in a single node. For example,
.simulate('click') calls the
onClick prop function. Shallow rendering isolates the node under test, which adds focus.
Enzyme comes with an adapter for each version of React. So,
enzyme-adapter-react-16 works on React 16.4 or above. For React 16.3.0 use the
enzyme-adapter-react-16.3 adapter. For Jest 15+, Enzyme no longer needs any special configuration. To write tests, import React, Enzyme functions, and system under test at top.
import React from 'react'; import shallow from 'enzyme'; import Foo from '../Foo'; describe('A killer test suite', () => it('should shallow render without a browser', () => const component = shallow(<Foo />); const result = component.contains(<div className="foo">Bar</div>); expect(result).toBe(true); ); );
Shallow rending has a wide range of selectors and functions to find nodes. Plucking one node at a time lets you assert functionality in an isolated manner.
- shallow rendering isolates React components
- rich API for finding nodes of interest
- no need for a headless browser
- adapters can be hazardous with every React upgrade
React offers a component-based approach to building web apps, but React by itself does not include any components. ExtReact offers pre-built components like menus, grids, charts, and forms to deliver functionality. The open source community is big and there are many components available; however fighting compatibility issues between many component libraries and React is daunting. A better idea is to reduce risk by getting as many components from fewer libraries, or at best a single library. ExtReact offers the most complete set of components in one professional package and includes commercial support.
To begin you’ll need Node 8.11+, NPM 6+, and Java 8 & 11. With a free trial, you can login to the NPM repository at npm.sencha.com. Install the app generator with
npm install -g @sencha/ext-react-gen. Then, create an app with
ext-react-gen app killer-app. This generates an app named
killer-app. Go into the project folder and do an
npm start to fire up a barebones React app.
Import ExtReact components from the
ext-react package. A component may come with its own store to get data. Many props are available with pre-built functionality. For example,
onSelect tells the
List component what to do when clicking on a list item. Sorters are available to sort list items in the component.
So, say you want to import a basic
import React, Component from 'react'; import List from '@sencha/ext-modern'; export default class BasicList extends Component store = Ext.create('Ext.data.Store', autoLoad: true, proxy: type: 'rest', url: 'data/people.json' , sorters: ['first_name'] ); tpl = data => ( <div> <div>data.first_name</div> </div> ); onSelect = (list, record) => console.log(`$record.get('first_name')`); ; render() return ( <List shadow itemTpl=this.tpl store=this.store onSelect=this.onSelect /> );
ExtReact offers more than 115 pre-built UI components with full commercial support. ExtReact components are made for seamless integration over the lifetime of the app.
- wide array of pre-built React components
- fewer dependencies over the many open source options
- professional components with commercial support
React Developer Tools lets you inspect React components right in the browser. It can inspect a hierarchy of components, with props and state. Ships as a browser extension for both Chrome and Firefox, and a stand-alone app. Users with Opera can install the Chrome extension with Chrome extensions enabled. The extension icon lights up on websites using React and says to open the developer tools.
On React apps, note the React tab in the developer tools. Clicking the tab shows a hierarchy of components in a tree view. Components with state show a tree collapse button that has a different color. You can navigate the tree with the arrow keys or
hjkl like using Vim. Right clicking gives you options like show in elements pane, scroll into view, or show source code.
The side pane gives you more insights into each component. It lets you make changes in the browser and highlights those changes. You can manipulate props and state plus store objects as a global variable.
Use the search bar to find components by name. This saves you time when there are many components in a tree. The search bar supports regex to make precise searches. One tip is to find the component using the regular DOM inspector or elements tab. Pick the element off the page and switch over to the React tab. The component gets selected in the React tree. Right clicking has the option to “Find the DOM node” which takes you back to the regular tab.
- helps to visualize React components in a tree
- manipulate and debug components at will
- helpful search tools to find components
- extra add-on, but does offer a stand-alone version
Redux Developer Tools support hot reloading and action replay. Ships as a browser extension, stand-alone app, and React component. The React component lives inside the host app. The tool lets you inspect every state and action payload. Or, go back in time by canceling actions. Making code changes re-evaluates actions marked as staged.
Install the extension through the Chrome Web Store or Mozilla Add-ons. The React component is available for browsers that do not support the extension. Changes to your project are necessary to use the extension. The extension must be set up in the Redux store, along with extension options.
For example, to set up the Redux Developer Tools with options:
const store = createStore( window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__( actionCreators, trace: true, traceLimit: 5 ) );
Actions available in the Dispatcher come from
actionCreators. This is a list of action functions. Import all actions of interest from the project into this variable. Tracers will include the stack trace for every dispatched action. Inspecting the trace tab allows clicking to jump into the code. The default value for this option is false. A trace limit sets the maximum stack frames shown, the default is 10.
Applying any middleware in the store requires
composeWithDevTools. Get this function from the
redux-devtools-extension NPM package. The
applyMiddleware function goes into this function as a parameter. This allows the dev tool to work alongside middleware.
- app state time traveling tool
- keeps track of code changes with hot reloading
- debug stack traces per action
- set up requires code changes in the project
Middleware that throws an error when mutating state either in or between dispatchers. Reducers assume arguments do not mutate state. Every time reducers return state, it must be a new object. A good practice is to avoid mutating state outside the reducer. This requires a lot of discipline from the programmer. So, a good idea is to automate this inspection through a tool.
The tool is useful to catch bugs during development only. It does a lot of object copying to enforce immutability. This means high memory consumption which degrades app performance. For this reason, do not enable this tool in production. One idea is set an environment variable
NODE_ENV, for example, to
To use this library as middleware:
import applyMiddleware, createStore from 'redux'; let middleware = ; if (process.env.NODE_ENV !== 'production') middleware.push(require('redux-immutable-state-invariant').default()); const store = createStore( applyMiddleware(...middleware) );
If you’re not mutating state, then the tool disappears. Mutate state in or between dispatchers and the tool yells with an error message. It keeps you at your best programming behavior like any good tool should.
- seamless and works with any workflow
- automates programming discipline
- throws errors with a descriptive message
- lots of object copying affects performance, but only enable this in dev
An action logger for Redux. Captures dispatcher actions in the browser’s log console. Comes with many options and allows insight into each dispatched action. As actions ripple through the app, this captures and lets you drill into each action. Each log entry captures both previous and current state, and the dispatcher’s action. Think of each action as a log message. The logger lets you see what these messages look like as they change state in the app.
To use the logger, set it up in the Redux store:
import applyMiddleware, createStore from 'redux'; import logger from 'redux-logger'; const store = createStore( applyMiddleware(logger) );
Make sure the logger is the last argument in
applyMiddleware so it captures actions. Options are available to change the logger’s behavior. You’ll need to import
redux-logger. Then, call the
createLogger function with an options object. For example,
predicate specifies a function that gets called before each action. Doing
(getState, action) => action.type !== UP_COUNT filters out actions that up the count. A
collapsed option is a function that returns true if the log group should collapse. Doing
(getState, action) => action.type === DOWN_COUNT collapses action types that reduce the count.
- captures dispatcher actions like log messages
- lets you drill into each action and inspect app state
- options let you tweak what is captured
- client-side logger only, but you can send messages across with a bit of effort
React’s usefulness stems from being a collection of tools and libraries that work well. These tools are often lightweight so you can plug-and-play at will. Programming is not reinventing the wheel but reusing existing solutions that work well. React’s popularity stems from the fact you can pick and choose what solves the immediate problem. This lets you focus on problems that don’t already have a good solution.