INTRODUCTION

What is Redux?

Redux is a state management framework that can be used with a number of different web technologies, including React
In Redux, there is a single state object that's responsible for the entire state of user's application

REDUX STRUCTURE

const myDefaultState = {myProperty: myValue};

const myReducer = (state=myDefaultState, action) => {
return myNewState;
};

const myReduxStore = Redux.createStore(myReducer);

const myAction = {type: myValue};

const myActionCreator = () => {
return myAction;
};

myReduxStore.dispatch(myActionCreator());

Redux Store

Whenever any piece of the app wants to update state, it must do so through the Redux store
The unidirectional data flow makes it easier to track state management in the app
createStore() Method
const myReduxStore = Redux.createStore(myReducer);
The createStore() method specifies a Redux store which it is an object that holds and manages application state
The createStore() method takes myReducer function as a required argument
getState() Method
myReduxStore.getState();
The getState() method can retrieve the current state held in the Redux store object
subscribe() Method
myReduxStore.subscribe();
The subscribe() method allows user to subscribe listener functions to the store, which are called whenever an action is dispatched against the store

Redux Action

const myAction = {type: myValue};
A Redux action is simply a JavaScript object that contains information about an action event that has occurred
The Redux store receives these action objects, then updates its state accordingly
Sometimes a Redux action also carries some data
For example, the action carries a username after a user logs in
While the data is optional, actions must carry a type property that specifies the "type" of action that occurred
Action Creator
const myActionCreator = () => { return myAction; }
An action creator is used to send the action to the Redux store so it can update its state
The action creator is simply a JavaScript function that returns an action
In other words, action creators create objects that represent action events
dispatch() Method
myReduxStore.dispatch(myActionCreator());
myReduxStore.dispatch( {type: myValue} ); (Alternate dispatch event)
The dispatch() method is used to dispatch actions to the Redux store
In Redux, all state updates are triggered by dispatching actions
Calling dispatch() method and passing the value returned from an action creator sends an action back to the Redux store

Redux Reducer

const myReducer = (state=myDefaultState, action) => { return myNewState; };
A Redux reducer is a function that responsible for the state modifications that take place in response to actions
The reducer has no side effects, which it never calls an API endpoint and it never has any hidden surprises
The myReducer takes state and action as arguments, and it always returns a new state
Another key principle in Redux is that state is read-only
In other words, the reducer function must always return a new copy of state and never modify state directly
Redux does not enforce state immutability, however, user are responsible for enforcing it in the code of the reducer functions
Handling an action
const myDefaultState = {login: false};

const myReducer = (state=myDefaultState, action) => {
if (action.type === "LOGIN") { return {login: true}; }
else { return state; }
};

const myReduxStore = Redux.createStore(myReducer);

const myLoginAction = () => {
return {type: "LOGIN"};
};

A common practice when working with Redux is to assign action types as read-only constants, then reference these constants wherever they are used
User can refactor the code there're working with to write the action types as const declarations
It's generally a convention to write constants in all uppercase, and this is standard practice in Redux as well

const MYLOGINACTION = "LOGIN";
const myDefaultState = {login: false};

const myReducer = (state=myDefaultState, action) => {
if (action.type === "LOGIN") { return {login: true}; }
else { return state; }
};

const myReduxStore = Redux.createStore(myReducer);
Handling multiple actions with switch statement
There is a situation where user are managing user authentication in the Redux store
User want to have a state representation for when users are logged in and when they are logged out
User need action creators that create actions corresponding to user login and user logout, along with the action objects themselves
At this point, the state immutability is not to be worried about since it is small and simple in the following example
For each action, user can return a new object, like {authenticated: true}
Plus, the default case in switch statement must be included
This is important because once the app has multiple reducers, they are all run any time an action dispatch is made, even when the action isn't related to that reducer
In such a case, user want to make sure that the statement return the current state

const MYLOGIN = "LOGIN";
const MYLOGOUT = "LOGOUT";
const myDefaultState = {authenticated: false};

const myAuthentication = (state=myDefaultState, action) => {
switch (action.type) {
case MYLOGIN: return {authenticated: true};
case MYLOGOUT: return {authenticated: false};
default: return myDefaultState;
}
};

const myReduxStore = Redux.createStore(myAuthentication);

const myLoginAction = () => {
return {type: MYLOGIN}
};

const myLogoutAction = () => {
return {type: MYLOGOUT}
};
combineReducers() Method
Redux.combineReducers();
The combineReducers() method accepts an object as an argument in which user define properties which associate keys to specific reducer functions
The name user give to the keys will be used by Redux as the name for the associated piece of state

const INCREMENT = "INCREMENT";
const DECREMENT = "DECREMENT";

const counterReducer = (state=0, action) => {
switch(action.type) {
case INCREMENT: return state + 1;
case DECREMENT: return state - 1;
default: return state;
}
};

const LOGIN = "LOGIN";
const LOGOUT = "LOGOUT";

const authReducer = (state = {authenticated: false}, action) => {
switch(action.type) {
case LOGIN: return {authenticated: true};
case LOGOUT: return {authenticated: false};
default: return state;
}
};

const rootReducer = Redux.combineReducers( {
count: counterReducer,
auth: authReducer
} );

const store = Redux.createStore(rootReducer);

Redux Thunk Middleware

Redux.applyMiddleware()