Bootcamp Notes – Day 13 (Wed) – React: Week 4 – Introduction to Redux
Introduction to Redux
The MVC Design Pattern
In software development you will often read or hear people mention something called MVC or one of it’s variants such as MVVM, or MVA. You may also sometimes hear it called the MVC framework (not a framework like Bootstrap). But it is not a framework in the sense that Bootstrap or Angular is a framework. Instead, MVC is what as known as a software design pattern. It is not a library, it doesn’t consist of any actual code at all. What it is is a reusable approach for how to structure an applications code. The MVC design pattern was formally introduced back in the 70’s, for use with with developing user interfaces for desktop applications. Typically MVC is used to develop presentation layer/client-side. It is not a pattern that’s used for the entire application, but for developing the presentation layer of the application the UI. Since then it has become very popular in web development as well. Today, popularly used in web applications.
A key concept of MVC lies in it’s separation of concerns. Separation of concerns in software development facilitates independent development, testing, maintenance of different parts of an app. Not to mention independent testing and maintenance. With MVC, the presentation layer is divided into three parts: Model, View, Controller
- MODEL: handle application state and logic
- VIEW: present information to user
- CONTROLLER: mediate between model and view
- The model stores the main application logic and data for the front end. Think of it as not a database but the data that’s been loaded into the application from the database and the front-end code that sends request to and receives data from the database. It will also respond to queries from the front end such as queries about its state, which usually come from the view and it will respond to request to change its state which come from the controller. It may also be set up to automatically send out notifications to the view or controller when any changes are made to it
- The view renders the model into a form suitable for display. Typically a UI element. The view can query the model directly for information about the application state, so that it can adjust itself.
- The controller receives information from the view, such as if a user submits data through an input element. Then it can process and relay that that information to the model and instruct the model to change it’s state. It can also send instructions to the view to make changes.
The the MVC pattern is very common in programming and you should know about it, React does NOT use MVC!
React state management is often handled with a newer design pattern called Flux.
We will be using a state management library called Redux, which owes some of its parentage to Flux.
The Flux Architecture
Initially, React developers (at Facebook) used React with the MVC pattern, especially for creating the View. But, they found that MVC did not scale well for a complex, large application like Facebook, with many thousands of components. MVC became unpredictable at scale, difficult to add new features without causing unexpected cascading effects in other parts of the code: bugs. Largely due to the bi-directional design of MVC data flow.
You can see in this diagram the complexity of MVC. Once small change in the app could cause the whole thing to bug crazy!
So the engineers at Facebook came up with a new design pattern or architecture that they call FLUX! Like MVC, it is an approach on how to structure on the front end. It can be considered an evolution of MVC. The key feature of Flux that sets it apart from MVC is: It has one way data flow.
It separates into action, dispatcher, store, view
- Once central dispatcher, multiple stores
- One Dispatcher acts as traffic controller, routes actions to the appropriate stores
- Stores hold application state and logic. There can be multiple stores.
- Views update when stores are changed.
Redux a popular JavaScript state management library influenced by FLUX!
Overview: Redux
Flux is an architecture/design pattern that describes an approach to structuring an application’s front end.
A design pattern does not provide actual code.
JavaScript libraries that implement Flux include: Flummox, Alt, Redux
Redux has some differences from FLUX but is inspired/influenced by FLUX and can be considered an evolution. Created by Dan Abramov for use with React, co-written with Andrew Clark, author of Flummox. Aside from FLUX, also inspired/influenced by: the ELM functional programming language and three JavaScript libraries: Immutable.js, Baobab.js, RxJS
Redux is a “predictable state container for JavaScript apps.”
Provides code that stores application state and a consistent way to access and update that state from anywhere in the application. Not just for React – can be used with any JavaScript application. Redux could be used with Vanilla JavaScript, with backbone.js and amber.js
Now in our course project application which is quite simple: the container component Main stores state and passes data as props to several presentational components; changes to state only occur in Main. In the real world, we have have 100’s or 1000’s of components with more complicated hierarchies and groupings. State management becomes more tricky at scale; Redux handles predictable, consistent state management.
Redux is very helpful at scale!
FUNDALMENTAL PRINCIPLES OF REDUX
There are three fundamental principles of Redux:
- Single Source of Truth
- State is Read-Only
- Changes are made with Pure Functions
Single Source of Truth
FLUX: There can be multiple stores; dispatcher directs actions to the right one.
Redux: Only one store; holds a single state object tree that contains the whole state of your application as objects within that tree.
Object tree: Tree-like data structure; each node contains an object; DOM is another example of an object tree.
State is read only
Only way to change state is with an action – an object that describes what happened
CHANGES ARE MADE WITH PURE FUNCTIONS
Changes are made with pure functions called reducers.
Pure functions are functions that have no side effects and given the same inputs, always returns the same outputs.
Example: Math.floor() is a pure function – given a number, always gives same result back, does nothing else; Math.random() is an impure function – will always give a different output.
A Redux reducer is a pure function that takes the previous state and an action and returns the next state.
Similar in concept to array methods like map that return a new array and do not mutate the original – Reducers always return new state objects instead of mutating the previous state.
Programming concept: immutability — data does not get mutated, only replaced by new data
Now replacing the entire state every time you need to make the smallest change might seem like overkill, but objects are cheap to create, and this approach creates advantages such a “time travel” – able to step back and forward from previous state.
Now, think of it like frames in an animation sequence or a flipbook – instead of redrawing the frame/page, a new one is created with changes; you can flip back and forth!
Now let’s see REDUX IN PRACTICE
In the flux architecture we had actions, dispatcher, store and view.
In Redux we have: actions, reducers, a single store, and the view
The dispatcher in FLUX worked as a traffic controller that routed actions to different stores with only one store that is no longer a major role. But we still have a dispatch method in Redux. User interactions with the view trigger the dispatch of actions. The actions are sent to reducers and reducers create a new state, which is inside the store. Then the view will change based on the state. As in FLUX this is strictly a one-way data flow. Reducers don’t talk back to actions and the stores does not talk back to the reducers. Again, the data flows in one direction.
React-Redux-Library
To use Redux with React, you will install the react-redux-library. From this library will cover a few important functions that you will learn to use later:
createStore() – Creates the Redux store which holds the state (as an object tree)
connect() – Generates container component that wraps around other components to subscribe them to the store.
mapStateToProps() – Passed a callback to connect() function. Called whenever state changes. Receives entire state tree & returns an object that contains only the data needed by the component.
Will also use a React Redux component named <Provider>: Which wraps around the root component of the app. Takes the store variable as an attribute. Makes store accessible to all child components that are connected using connect() function.
Exercise: Introduction to Redux
- First, install Redux and React-Redux into your application as follows, with Yarn:
yarn add redux@4.0.5
yarn add react-redux@7.2.0
- Next, create a folder named redux inside the src folder.
- Inside the src/redux folder, add a file named reducer.js with the code below:
import { CAMPSITES } from '../shared/campsites';
import { COMMENTS } from '../shared/comments';
import { PARTNERS } from '../shared/partners';
import { PROMOTIONS } from '../shared/promotions';
export const initialState = {
campsites: CAMPSITES,
comments: COMMENTS,
partners: PARTNERS,
promotions: PROMOTIONS
};
export const Reducer = (state = initialState, action) => {
return state;
};
- Then, add a file named configureStore.js in the redux folder and add the following code to it:
import { createStore } from 'redux';
import { Reducer, initialState } from './reducer';
export const ConfigureStore = () => {
const store = createStore(
Reducer,
initialState
);
return store;
};
App.js
MainComponent.js
Exercise: React Redux Form
Exercise: React Redux Form Validation
Additional Resources:
- Guru99 – MVC Tutorial for Beginners
- Hackernoon – From MVC to Modern Frameworks
- Medium.com – Understanding MVC Architecture with React
- Facebook – Flux
- Flux Architecture In Depth Overview
- Intro to Flux and Redux
- A Cartoon Guide To Flux
- Redux
- React and Redux
- Redux Basics Documentation
- React-Redux library
- A list of Redux tutorials
- Getting started with Redux – A tutorial by Dan Abramov (creator of Redux)
- Redux createStore()
- React-Redux
- React-Redux – <Provider>
- React-Redux mapStateToProps()
- React-Redux connect()
- React Router – withRouter()
- React Redux Form
- React Redux Form – LocalForm
- React Redux Form – Control
- Using React Redux Form
- How to populate react-redux-form with dynamic default values
- Should you store your form state in Redux?
- Other Redux-compatible form libraries:
- React-Redux-Form – Control component
- React-Redux-Form – Errors component