As technology continues to evolve, single page applications (SPA), along with microservice-based backends become more and more popular. Single page application does not require page reloading during use once it has been loaded the first time, which means it’s more user friendly faster than legacy UI made by something like JSP, PHP, ASP, etc.
There are various techniques available that enable the browser to retain a single page even when the application requires server communication. In this article, I’m going to introduce how to make that with React. You need to have a quick look at basic tutorials in regards to npm, react components, babel, webpack. The code is available in Github:
1. Architecture Chart
This is an UI MVC architecture chart. The view is React class component with its own states, constants, actions(events), reducers(event handlers), containers(connect to Redux global store). The model and controller are Redux store, which acts as a global centralized manager, dispatching actions and executing reducers. The state change will in turn result in React components updating.
2. React Components
By leveraging Redux concepts, we can make React components clean and well-organized. As illustrated below, we can see there are actions, constants, containers, reducers, and main class in each component folder.
Let’s take login page as an example.
type property that indicates the type of action being performed. You send them to the store using
store.dispatch(). The functions that dispatch actions are called action creators, such as
logIn. For the
logIn function, we leverage redux-thunk middleware to perform asynchronous dispatches. This is really useful when you need to do conditional dispatches.
The reducer is a pure function that takes the previous state and an action, and returns the next state. The concept comes from map-reduce. Redux also provides a
combineReducers helper function to merge separate reducing functions from different components into a single reducing function so that we can pass to
Container components are used to connect/subscribe to Redux store, which means it can bind to redux store state change and actions.
2.4 React Components
In this example, we still use React class components, however, since the latest React version has introduced hooks to functional components, it’s no longer recommended to use class components. We can dispatch redux actions just like calling a methods thanks to react-redux connect component (illustrated in 2.3).
In the stores.js, we create a global store and register redux middleware, such as logger and thunk.
All React container components need access to the Redux store so they can subscribe to it. It’s recommended to use
<Provider> to make the store available to all container components in the application without passing it explicitly. You only need to use it once when you render the root component. Please check index.js to see how to pass the Redux store.
Routers play a key role in single page application. Its most basic responsibility is to dynamically render some UI(partly) when its
path matches the current URL. It needs Link tag to work together with html navigation tags.
5. Service Worker
First of all, you may ask why we need a service worker. Suppose you have an e-commerce web site which is a single page application. You navigate to shopping cart from index page, and you won’t have any issues thanks to UI router mechanism. But if you open a new window and paste URL like “localhost/cart/” to the browser to visit the shopping cart, then it will send the request – “localhost/cart/” to backend to fetch the page. Obviously you will get 404 error. Service worker comes out for this scenario.
In my example, I use webpack sw-precache-webpack-plugin to handle that.