We are going to use the following stack:
react-router
v4 and react-router-config
mocha
, chai
SuperTest
and cheerio
.Authentication and Database Middleware
mongoose
- object modeling for our MongoDB databasepassport
- help us authenticating with different methodsAutomated Testing
mocha
sets up the unit test, while chai
helps you accomplish a unit test using asserts.SuperTest
spools up your Express server and sends requests to it.Once the requests come back, you can make assertions about the response.cheerio
is jQuery for Node. It'll help your server code parse HTML.Take the following steps to create a baseline app:
Follow this tutorial to set up a create-react-app
with react-hot-loader
React Hot Loader allows you to tweak React components in real time.
Follow this tutorial to set up the rest of the create-react-app
project to use react-router
. We are going to use Version 4.x of the React Router, which is a complete rewrite of Versions 3.x and prior.
Warning: Implementing the Build, Run & Develop section in the second tutorial could cause react-hot-loader
to not work so this section wasn't implemented in the baseline app, which is available for download on Github.
FullStackReact's Tutorial and Sample Project - A create-react-app
with server example
Isomorphic Webapp Book Chapter 2 Sample Code Learning
create-react-app
.File Structure
$ tree -l 3 --ignore 'node_modules'
looseleaf-node
├───package.json
├───.babelrc
├───.env <== #C
├───server
│ ├───server.js <== #B
│ ├───start-client.js
│ ├───run.js <== #A
│ ├───build
│ ├───data <== #A
│ ├───assets <== #A
│ └───api
| └───api1.js <== #A and #B
├───test
├───client
│ ├───package.json
│ ├───config
│ ├───public
| | └───favicon.ico
| | └───index.html <== #B
│ ├───src
│ | └───shared
| | | ├───Profile
| | | | ├── App.js <== #A
| | | | ├── HTML.js <== #A
| | | | ├── Header.js
| | | | ├── Home.js
| | | | ├── Main.js
| | | | ├── NotFound.js
| | | | └── routes.js <== #A
| | | └───Recipe
| | | ├── App.js
| | | ├── HTML.js
| | | └── ...
│ | ├───AppUser.js <== #B
│ | └───index.js <== #B
│ | └───main.js <== #A
| ├───iso-middleware
| | ├── renderRoute.jsx <== #D
| | └── renderView.jsx <== #D
Notes
index.js
and index.html
are the entry points. index.js
renders component that attaches to the root componnent identified in the index.html
file.Facebook provides a command-line utility called
create-react-app
which automatically sets up a new React project with a sensible default project structure and feature set. This is the best way to get started as a beginner.You'll likely outgrow this option pretty quickly as you get a better grasp of React and want to customize your stack. Fortunately, create-react-app offers an
eject
option to export your app, so you're not locked in.
Create React App is agnostic of the backend, and just produces static HTML/JS/CSS bundles.
Before running the app, you have to set up a few things:
From the project directory, run the command:
$ npm install && cd client && npm install && cd ..
$ mkdir server/build
This installs all the dependencies in your package.json
from for both the server and the client. Everytime you make changes to package.json
, npm install
needs to be run so that the dependencies defined in the file would get downloaded by npm. The dependencies gets downloaded into a folder called node_modules.
Set up your database for the app:
MongoDB
$ brew install mongodb
$ sudo mkdir -p /data/db
Set permissions for the data directory:
$ sudo chown -R `whoami` /data/db
$ mongod
$ mongo
Some useful commands to run in the mongo shell
> use test $ switch to db test
> show collections $ list all collections inside current db
users
> db.users.find() $ in the users collection, return all documents
> db.users.remove( { } ) $ remove all documents in the users collection
> db.users.remove( { index } )
> db.users.dropIndexes()
Check out Azat Marda's Cheatsheet, Quick Reference, and Little Mongo Handbook for more useful commands.
If you are developing on the client side only, $ cd client
then $ npm run build
or $ yarn build
- Build the project. For production builds, you'll want to use npm run build
to build an optimized bundle and transpiled down to ES5, which will be saved to the filesystem. If you don't have hot reloading enabled, you have to run this after making changes to your source code to allow the changes to take effect next time you start the client server. This is undesirable and there are a few workarounds, in particular, nodemon and react-hot-reloader, which will be discussed in more detail below.
For developing an integrated client and server app, we want to run the isomorphic webapp with the following command line:
$ npm start
This will give us access to:
http://localhost:3001/api/hello If you are not seeing changes made to the client app, do the following, before running the start script again:
$ npm build-client
For developing an server and client separately
To run both the server and client in separately, do the following, which starts the server to automomatically listen on port 3001 (http://localhost:3001/) and the client to automomatically listen on port 3000 (http://localhost:3000/).
$ npm start-dev
If the single page application doesn't render correctly on the server, you need to do this:
# npm build-client
The npm start-dev
script is equivalent to running npm run start-server
and npm run start-client
concurrently. We learn how to do that from FullStackReact's Tutorial and Sample Project.
To run just the server app, do
$ npm run start-server
To run both the client and server app, do
$ npm start-dev
To run the client app, do
$ npm run start-client
Alternatively,
$ cd client && npm start
In this mode, you can use react-hot-loader
to make changes to react components in runtime.
Just go to http://localhost:3001/api/hello to see change being made.
If you want to run on other ports, like 9000, 8000, 8080, just specify the port you want:
$ PORT=9000 npm start
To run the server to serve static content:
$ yarn global add serve
$ serve -s build
In this mode, you can't use react-hot-loader
because the client app is rendered on the server side.
Stop the database server when you are done:
Stop the postgres database
$ pg_ctl -D /usr/local/var/postgres stop
Or if you use mongo: control
+C
redux
is a manager of global variables for React components.
Middleware
redux-thunk
- allows you to write action creators that return a function instead of an action. redux-thunk
allows you to delay the dispatch of an action or to dispatch only if a certain condition is met. A thunk is a function that wraps an expression to delay its evaluation.redux-promise
- receives a promise, dispatch the resolved value of the promise, but will not dismatch anything if the promise rejects.redux-logger
- logging tool that lets you replay problems as if they happened in your own browser.react-redux
- We need to use connect
from react-redux
to connect a React component to a Redux store.morgan
- log every request to the consolebody-parser
- get information from html formsSee the tutorial for how to set up passport
and postgresql
with your react-node app.
We also need to create a controller for creating the User
object after the user enters all the required information:
$ mkdir controllers
$ touch controllers/user.js
The user
controller will include logic for creating a new user and authenticating a returning user. The user
controller relies on the User
model for creating a new User
. The user
controller requires the following dependencies:
async
- We will be using async.waterfall
a lot, which:
Runs the tasks array of functions in series, each passing their results to the next in the array. However, if any of the tasks pass an error to their own callback, the next function is not executed, and the main callback is immediately called with the error.
nodemailer
- a module for Node.js applications to allow easy as cake email sending.jsonwebtoken
moment
- is a lightweight Javascript date library for parsing, validating, manipulating, and formatting dates.request
- Request is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.querystring
- Node's utilities for parsing and formatting URL query strings.Oauth
moment
, which is a lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates.react-cookie
, which lets you load and save cookies with React.We are using materialize-css
, which depends on jquery
. Add the following to the client project:
$ cd client
$ npm install --save materialize-css
$ npm install --save jquery
$ touch src/assets/index.css
The index.css
is where the custom styles for you app go. This will override the materialize-css
style if you add the following imports to your index.js
(or whatever the main entry point of your client app is):
// src/index.js
import 'materialize-css'
import 'materialize-css/dist/css/materialize.min.css';
import './assets/index.css';
To use materialize components in your react components, import jquery
and add the script in componentDidMount
:
// src/components/Header.js
import React from 'react'
import { Link } from 'react-router-dom'
import $ from 'jquery'
class Header extends React.Component {
componentDidMount() {
$(".dropdown-button").dropdown()
}
render() {
// TODO: nav and dropdown menu
}
What about CSS javascripts? Read the full stack react tutorial for more on that.
morgan
- quest logger middleware for node.jswebpack
]()babel
]()immer
- a tiny package that allows you to work with immutable state in a more convenient way. It is based on the copy-on-write mechanism.mobx
- Simple, scalable state managementUse Webpack because it allows for hot module replacement. Webpack is a prerequisite for
react-hot-reloader
, which lets you update your react components during runtime without restarting the server via anpm run build
.