This project was partially bootstrapped with Create React App.
Below you will find some information on how to perform common tasks.
- Folder Structure
- Available Scripts
- Required Polyfills
- Importing a Component
- Running Tests
- Developing Components in Isolation
- Deployment
After creation, your project should look like this:
my-app/
README.md
node_modules/
package.json
public/
index.html
favicon.ico
src/
App.css
App.js
App.test.js
index.css
index.js
logo.svg
For the project to build, these files must exist with exact filenames:
public/index.html
is the page template;src/index.js
is the JavaScript entry point.
You can delete or rename the other files.
You may create subdirectories inside src
. For faster rebuilds, only files inside src
are processed by Webpack.
You need to put any JS and CSS files inside src
, otherwise Webpack won’t see them.
Only files inside public
can be used from public/index.html
.
Read instructions below for using assets from JavaScript and HTML.
You can, however, create more top-level directories.
They will not be included in the production build so you can use them for things like documentation.
In the project directory, you can run:
Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
Runs the integration tests with Selenium Webdriver. Requires running npm start
in another tab.
Builds the app for production to the build
folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about deployment for more information.
Note: this is a one-way operation. Once you eject
, you can’t go back!
If you aren’t satisfied with the build tool and configuration choices, you can eject
at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject
will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use eject
. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
Note: this feature is available with
[email protected]
and higher.
Read the migration guide to learn how to enable it in older projects!
Create React App uses Jest as its test runner. To prepare for this integration, we did a major revamp of Jest so if you heard bad things about it years ago, give it another try.
Jest is a Node-based runner. This means that the tests always run in a Node environment and not in a real browser. This lets us enable fast iteration speed and prevent flakiness.
While Jest provides browser globals such as window
thanks to jsdom, they are only approximations of the real browser behavior. Jest is intended to be used for unit tests of your logic and your components rather than the DOM quirks.
We recommend that you use a separate tool for browser end-to-end tests if you need them. They are beyond the scope of Create React App.
Jest will look for test files with any of the following popular naming conventions:
- Files with
.js
suffix in__tests__
folders. - Files with
.test.js
suffix. - Files with
.spec.js
suffix.
The .test.js
/ .spec.js
files (or the __tests__
folders) can be located at any depth under the src
top level folder.
We recommend to put the test files (or __tests__
folders) next to the code they are testing so that relative imports appear shorter. For example, if App.test.js
and App.js
are in the same folder, the test just needs to import App from './App'
instead of a long relative path. Colocation also helps find tests more quickly in larger projects.
When you run npm test
, Jest will launch in the watch mode. Every time you save a file, it will re-run the tests, just like npm start
recompiles the code.
The watcher includes an interactive command-line interface with the ability to run all tests, or focus on a search pattern. It is designed this way so that you can keep it open and enjoy fast re-runs. You can learn the commands from the “Watch Usage” note that the watcher prints after every run:
By default, when you run npm test
, Jest will only run the tests related to files changed since the last commit. This is an optimization designed to make your tests run fast regardless of how many tests you have. However it assumes that you don’t often commit the code that doesn’t pass the tests.
Jest will always explicitly mention that it only ran tests related to the files changed since the last commit. You can also press a
in the watch mode to force Jest to run all tests.
Jest will always run all tests on a continuous integration server or if the project is not inside a Git or Mercurial repository.
To create tests, add it()
(or test()
) blocks with the name of the test and its code. You may optionally wrap them in describe()
blocks for logical grouping but this is neither required nor recommended.
Jest provides a built-in expect()
global function for making assertions. A basic test could look like this:
import sum from './sum';
it('sums numbers', () => {
expect(sum(1, 2)).toEqual(3);
expect(sum(2, 2)).toEqual(4);
});
All expect()
matchers supported by Jest are extensively documented here.
You can also use jest.fn()
and expect(fn).toBeCalled()
to create “spies” or mock functions.
There is a broad spectrum of component testing techniques. They range from a “smoke test” verifying that a component renders without throwing, to shallow rendering and testing some of the output, to full rendering and testing component lifecycle and state changes.
Different projects choose different testing tradeoffs based on how often components change, and how much logic they contain. If you haven’t decided on a testing strategy yet, we recommend that you start with creating simple smoke tests for your components:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
});
This test mounts a component and makes sure that it didn’t throw during rendering. Tests like this provide a lot of value with very little effort so they are great as a starting point, and this is the test you will find in src/App.test.js
.
When you encounter bugs caused by changing components, you will gain a deeper insight into which parts of them are worth testing in your application. This might be a good time to introduce more specific tests asserting specific expected output or behavior.
If you’d like to test components in isolation from the child components they render, we recommend using shallow()
rendering API from Enzyme. To install it, run:
npm install --save enzyme enzyme-adapter-react-16 react-test-renderer
Alternatively you may use yarn
:
yarn add enzyme enzyme-adapter-react-16 react-test-renderer
As of Enzyme 3, you will need to install Enzyme along with an Adapter corresponding to the version of React you are using. (The examples above use the adapter for React 16.)
The adapter will also need to be configured in your global setup file:
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
Note: Keep in mind that if you decide to "eject" before creating
src/setupTests.js
, the resultingpackage.json
file won't contain any reference to it. Read here to learn how to add this after ejecting.
Now you can write a smoke test with it:
import React from 'react';
import { shallow } from 'enzyme';
import App from './App';
it('renders without crashing', () => {
shallow(<App />);
});
Unlike the previous smoke test using ReactDOM.render()
, this test only renders <App>
and doesn’t go deeper. For example, even if <App>
itself renders a <Button>
that throws, this test will pass. Shallow rendering is great for isolated unit tests, but you may still want to create some full rendering tests to ensure the components integrate correctly. Enzyme supports full rendering with mount()
, and you can also use it for testing state changes and component lifecycle.
You can read the Enzyme documentation for more testing techniques. Enzyme documentation uses Chai and Sinon for assertions but you don’t have to use them because Jest provides built-in expect()
and jest.fn()
for spies.
Here is an example from Enzyme documentation that asserts specific output, rewritten to use Jest matchers:
import React from 'react';
import { shallow } from 'enzyme';
import App from './App';
it('renders welcome message', () => {
const wrapper = shallow(<App />);
const welcome = <h2>Welcome to React</h2>;
// expect(wrapper.contains(welcome)).to.equal(true);
expect(wrapper.contains(welcome)).toEqual(true);
});
All Jest matchers are extensively documented here.
Nevertheless you can use a third-party assertion library like Chai if you want to, as described below.
Additionally, you might find jest-enzyme helpful to simplify your tests with readable matchers. The above contains
code can be written more simply with jest-enzyme.
expect(wrapper).toContainReact(welcome)
To enable this, install jest-enzyme
:
npm install --save jest-enzyme
Alternatively you may use yarn
:
yarn add jest-enzyme
Import it in src/setupTests.js
to make its matchers available in every test:
import 'jest-enzyme';
Usually, in an app, you have a lot of UI components, and each of them has many different states. For an example, a simple button component could have following states:
- In a regular state, with a text label.
- In the disabled mode.
- In a loading state.
Usually, it’s hard to see these states without running a sample app or some examples.
Create React App doesn’t include any tools for this by default, but you can easily add Storybook for React (source) or React Styleguidist (source) to your project. These are third-party tools that let you develop components and see all their states in isolation from your app.
You can also deploy your Storybook or style guide as a static app. This way, everyone in your team can view and review different states of UI components without starting a backend server or creating an account in your app.
Storybook is a development environment for React UI components. It allows you to browse a component library, view the different states of each component, and interactively develop and test components.
First, install the following npm package globally:
npm install -g @storybook/cli
Then, run the following command inside your app’s directory:
getstorybook
After that, follow the instructions on the screen.
Learn more about React Storybook:
- Screencast: Getting Started with React Storybook
- GitHub Repo
- Documentation
- Snapshot Testing UI with Storybook + addon/storyshot
npm run build
creates a build
directory with a production build of your app. Set up your favorite HTTP server so that a visitor to your site is served index.html
, and requests to static paths like /static/js/main.<hash>.js
are served with the contents of the /static/js/main.<hash>.js
file.
Note: this feature is available with
[email protected]
and higher.
The step below is important!
If you skip it, your app will not deploy correctly.
Open your package.json
and add a homepage
field for your project:
"homepage": "https://myusername.github.io/my-app",
or for a GitHub user page:
"homepage": "https://myusername.github.io",
Create React App uses the homepage
field to determine the root URL in the built HTML file.
Now, whenever you run npm run build
, you will see a cheat sheet with instructions on how to deploy to GitHub Pages.
To publish it at https://myusername.github.io/my-app, run:
npm install --save gh-pages
Alternatively you may use yarn
:
yarn add gh-pages
Add the following scripts in your package.json
:
"scripts": {
+ "predeploy": "npm run build",
+ "deploy": "gh-pages -d build",
"start": "react-scripts start",
"build": "react-scripts build",
The predeploy
script will run automatically before deploy
is run.
If you are deploying to a GitHub user page instead of a project page you'll need to make two additional modifications:
- First, change your repository's source branch to be any branch other than master.
- Additionally, tweak your
package.json
scripts to push deployments to master:
"scripts": {
"predeploy": "npm run build",
- "deploy": "gh-pages -d build",
+ "deploy": "gh-pages -b master -d build",
Then run:
npm run deploy
Finally, make sure GitHub Pages option in your GitHub project settings is set to use the gh-pages
branch:
You can configure a custom domain with GitHub Pages by adding a CNAME
file to the public/
folder.
GitHub Pages doesn’t support routers that use the HTML5 pushState
history API under the hood (for example, React Router using browserHistory
). This is because when there is a fresh page load for a url like http://user.github.io/todomvc/todos/42
, where /todos/42
is a frontend route, the GitHub Pages server returns 404 because it knows nothing of /todos/42
. If you want to add a router to a project hosted on GitHub Pages, here are a couple of solutions:
- You could switch from using HTML5 history API to routing with hashes. If you use React Router, you can switch to
hashHistory
for this effect, but the URL will be longer and more verbose (for example,http://user.github.io/todomvc/#/todos/42?_k=yknaj
). Read more about different history implementations in React Router. - Alternatively, you can use a trick to teach GitHub Pages to handle 404 by redirecting to your
index.html
page with a special redirect parameter. You would need to add a404.html
file with the redirection code to thebuild
folder before deploying your project, and you’ll need to add code handling the redirect parameter toindex.html
. You can find a detailed explanation of this technique in this guide.