Create React App and React Router 4 Developer Workflow
Prerequisites
Run time environment and package manager: Node, npm and yarn
Code editor: VS Code is my preference https://code.visualstudio.com/
Terminal App: Hyper is my preference https://hyper.is/
Install and Setup npm scripts
- Create a folder for your project and then, use your terminal app to cd into it. Open the folder in your code editor as well
npx create-react-app my-app
2. cd into the app folder and then run the command for ESLint Initialise
Use the popular airbnb style guide and select .json for the eslint file. Select yes for React and to install peerDependencies
yarn add eslint --dev
./node_modules/.bin/eslint --init
Install prettier and eslint plugins
yarn add prettier eslint-plugin-prettier eslint-config-prettier --dev
ESLint Config file with Prettier Integration for formatting
It is better to do it in the ESLint file, instead of using the Prettier plugin for your code editor. Because this way it is more portable, and you can debug using the command line as well as, transfer your workflow to other systems by just using the .eslintrc.json file.Integrating with ESLint · Prettier https://prettier.io/docs/en/eslint.html
GitHub — prettier/eslint-plugin-prettier: ESLint plugin for prettier formatting https://github.com/prettier/eslint-plugin-prettier
GitHub — prettier/eslint-config-prettier: Turns off all rules that are unnecessary or might conflict with Prettier. https://github.com/prettier/eslint-config-prettier
If there are any problems you can always, revert to using the Prettier code editor plugin and setup.
Copy the below code, into your .eslintrc.json file
{
"extends": [
"airbnb",
"prettier/react"
],
"plugins": [
"prettier"
],
"env": {
"browser": true,
"jasmine": true
},
"rules": {
"react/jsx-filename-extension": [
1,
{
"extensions": [
".js"
]
}
],
"react/prefer-stateless-function": [
0,
{
"ignorePureComponents": true
}
],
"prettier/prettier": [
"error",
{
"trailingComma": "none",
"singleQuote": true,
"printWidth": 100
}
]
}
}
Add the linting script to the package.json file
"lint": "eslint ."
Fix ESlint errors
registerServiceWorker.js comes with create-react-app and we should not have to worry about linting it, just in case it causes errors.
Create a .eslintignore file in the root directory (the same folder with the .eslintrc.json file in it. And add src/registerServiceWorker.js to the first line and save.
CLI Run Commands
Run the App and styles from one terminal window. And do the linting in another window. The App should be live at http://localhost:3000 and linting should be working in your javascript files now.
Running the App
yarn start
Linting .js files
yarn lint
Creating a production build
yarn build
React.js Project Folder Setup
- Create folders for css, components and assets. Put them in the src folder.
css folder — used for css files
components folder — used for javascript component files
assets folder — used for media such as images, videos, icons etc…
2. Delete the files index.css and logo.svg. Delete the index.css import code in index.js
import './index.css';
3. Remove references of logo in App.js
import logo from './logo.svg';<img src={logo} className="App-logo" alt="logo" />
4. Decide whether you want to use Stylus or Sass as your preprocessor. Move App.css to the css folder. Create either a App.styl or App.scss file inside it.
5. Delete all of the styles inside of App.css and replace with the below, example boilerplate. Duplicate the code into your App.styl or App.scss file.
Alternatively you can write your own CSS this is only an example so that you can see it work.
:root {
--grey: #343436;
}
html {
font-size: 62.5%; /* font-size 1em = 10px on default browser settings */
}
body {
font-size: 1.6rem;
}
.container {
max-width: 1300px;
width: 100%;
}
Install Stylus or Sass
Stylus setup
yarn add stylus
Put (Under scripts in package.json)
"styles": "stylus -w ./src/css/App.styl -o ./src/css/App.css",
When we run this script it will compile every .styl file in the ./src/css folder, then save the compiled css in ./src/css folder every time we change a .styl file.
Make sure that the folders tree looks like below
└── src
└── css
├── App.css
└── App.styl
Sass setup
yarn add node-sass
Put (Under scripts in package.json)
"styles": "node-sass -w ./src/css -o ./src/css",
When we run this script it will watch every .scss file in the ./src/css folder, then save the compiled css in ./src/css folder every time we change a .scss file.
Make sure that the folders tree looks like below
└── src
└── css
├── App.css
└── App.scss
Update the import code in App.js to the below
import ‘./css/App.css’;
Install concurrently or npm-run-all
They allow you to run multiple scripts at the same time.
concurrently setup
yarn add concurrently
Put (Under scripts in package.json)
"watch": "concurrently \"yarn start \" \"yarn styles\"",
npm-run-all setup
yarn add npm-run-all --save-dev
Put (Under scripts in package.json)
"watch": "run-p start styles",
Running the App with styles
Run the command yarn watch to run the scripts and styles at the same time, no need for multiple terminal windows. One for scripts and one for styles etc… The App.styl/App.scss file will be the main file used for doing the CSS, so write your code in there. It will then convert and update the App.css file. You can do a test by adding a background color to the body to make sure that its working properly.
Install normalize.css
yarn add normalize.css
Import normalize.css into index.js
import 'normalize.css';
React App Folder Tree
└── my-app
├── README.md
├── node_modules
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
├── src
│ ├── App.js
│ ├── App.test.js
│ ├── Router.js
│ ├── assets
│ ├── components
│ ├── css
│ │ ├── App.css
│ │ └── App.styl
│ ├── index.js
│ ├── registerServiceWorker.js
│ └── views
└── yarn.lock
Optional Installs
Documentation for using styled-components in React https://www.styled-components.com/
Install Styled components
yarn add styled-components
Import into corresponding .js file when using
import styled from 'styled-components’;
React Router 4 Install and Setup
Install React Router
yarn add react-router-dom
- Create a folder for views and put it in the src folder.
- Create a Router.js file and put it in the root of the src folder
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import App from './App';const Router = () => (
<BrowserRouter>
<Switch>
<Route exact path="/" component={App} />
</Switch>
</BrowserRouter>
);export default Router;
3. Update the index.js file in the root of the src folder so it looks like the below
import React from 'react';
import ReactDOM from 'react-dom';
import 'normalize.css';
import Router from './Router';
import './css/App.css';
import registerServiceWorker from './registerServiceWorker';ReactDOM.render(<Router />, document.getElementById('root'));
registerServiceWorker();
Example setup with pages and 404 routes
App.js is the homepage, and subsequent pages are to be created in the views folder. Create components and put them in the components folder. Then import those components, into the pages you create in the views folder.
The NotFound.js file is the 404 page, which is the page that you get redirected to, when you have an invalid url in your search box.
Router.js file
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import App from './App';
import About from './views/About';
import NotFound from './views/NotFound';const Router = () => (
<BrowserRouter>
<Switch>
<Route exact path="/" component={App} />
<Route exact path="/about" component={About} />
<Route component={NotFound} />
</Switch>
</BrowserRouter>
)export default Router;
About.js file http://localhost:3000/about
import React, { Component } from 'react';class About extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<h1 className="App-title">About Page</h1>
</header>
<p className="App-intro">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis in urna sed nisl faucibus
suscipit. Proin diam erat, accumsan vel tincidunt id, tristique vel odio. Etiam ex lectus,
eleifend nec dignissim vel, lacinia eget diam. Pellentesque pulvinar imperdiet tortor,
eget varius erat tempus ut. Nunc dictum enim ac massa pharetra facilisis. Vestibulum at
pulvinar erat, vel venenatis purus. Integer ut vulputate augue, vitae molestie mi. Aliquam
imperdiet, est non pellentesque consequat, mauris elit rutrum nulla, aliquam pellentesque
arcu mi ac augue. Nulla iaculis eget mi ut cursus. Nullam nec ligula tincidunt, posuere
est vitae, placerat turpis. Vestibulum pellentesque, lorem quis dignissim tristique, ex
lacus sodales ligula, nec blandit ex nisl ac lorem.
</p>
</div>
);
}
}export default About;
NotFound.js http://localhost:3000/foobar
import React, { Component } from 'react';class NotFound extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<h1 className="App-title">404 Page Does Not Exist</h1>
</header>
</div>
);
}
}export default NotFound;
Page Navigation
The href attribute is required on an anchor. Provide a valid, navigable address as the href value. Add a href address to the link tag like below.
<Link href="/" to="/">
Home
</Link>
React App and React Router 4 Folder Tree
└── my-app
├── README.md
├── node_modules
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
├── src
│ ├── App.js
│ ├── App.test.js
│ ├── Router.js
│ ├── assets
│ ├── components
│ ├── css
│ │ ├── App.css
│ │ └── App.styl
│ ├── index.js
│ ├── registerServiceWorker.js
│ └── views
│ ├── About.js
│ └── NotFound.js
└── yarn.lock
*Bonus section*
Scroll to top Restoration
React Router: Declarative Routing for React.js https://reacttraining.com/react-router/
React Router: Declarative Routing for React.js https://reacttraining.com/react-router/web/guides/scroll-restoration
Most of the time all you need is to “scroll to the top” because you have a long content page, that when navigated to, stays scrolled down. This is straightforward to handle with a <ScrollToTop> component that will scroll the window up on every navigation, make sure to wrap it in withRouter to give it access to the router’s props:
The example code below works
import React from 'react';class ScrollStateTop extends React.Component {
componentDidMount(prevProps) {
window.scrollTo(0, 0);
}
render() {
return null;
}
}export default ScrollStateTop;
Document HTML Head and Meta tag setup (SEO)
React scripts for dynamic head meta (Choose one of them)
GitHub — nfl/react-helmet: A document head manager for React https://github.com/nfl/react-helmet
GitHub — s-yadav/react-meta-tags: Handle document meta/head tags in isomorphic react with ease. https://github.com/s-yadav/react-meta-tags
GitHub — kodyl/react-document-meta: HTML meta tags for React-based apps. Works for both client- and server-side rendering, and has a strict but flexible API. https://github.com/kodyl/react-document-meta
You need to have different meta descriptions on each page, its good for SEO.