This is the continuation of my previous article – Introduction to Redux – For Beginners. In this article we will see more on technical definition and syntax of each key word we discussed in the previous article. As I mentioned before, following are the most important Store, Actions, Reducers when it comes to Redux. Let’s dig deep into each terms,
Store:
Every application have state and we need to save this state somewhere so it can be accessed across the application and this is the reason we have Store to hold state of your whole application. The state of the application will be stored in an object of tree in a Single Store.
State is read only – The only way to change the state is to emit an action, an object describing what happened.
To create a Store ->
· createStore(reducer_name<function>, [preLoadedState<any_type>], [middleware<function>])
o reducer_name – It is a function with two argument (oldState, action) and returns newState. We will look more into this shortly. It can also be combined Reducers.
o preLoadedState – It is an optional argument to initial state. If we use multiple reducer in an application using combineReducers, then this argument should pass object same as the keys passed.
o middleware(enhancer) – It is also an optional argument to enhance the store. Act like a middle man between store and reducer. Only store enhancer with Redux is applyMiddleware() (This is handy for a variety of tasks, such as expressing asynchronous actions in a concise manner, or logging every action payload.)
· Store methods – getState(), dispatch() and subscribe()
o dispatch() – It is used to change the State. It looks for an event. If applyMiddleware is added in the application, then it interacts with dispatched actions before it reach the store.
o subscribe() – Updates UI if the State changes.
o getState() – To get current state.
var middleware = applyMiddleware(thunk, logger); //create STORE with two parameter that explains Reducer and preLoadedState - if it is combineReducers(then it will be having //definition for STATES) var store = createStore(completeReducers, middleware); //To listen to the store change, SUBSCRIBE it store.subscribe(() => { console.log("Store changed ", store.getState()) }) //Set DISPATCH (looking for Event) to the store, so state will be changed store.dispatch({ type: "CHANGE_NAME", name: "Buhari"}); store.dispatch({ type: "CHANGE_COUNTRY", country: "India"}); //For Async - Instead of Dispatching object from the Store, we can dispatch a function with an argument - inside the function we can call Dispatch //Like below we can call multiple action with single action store.dispatch((dispatch) => { dispatch({ type: "CHANGE_ COUNTRY ", country: "India"}) //axios make promise based http call, for more - https://github.com/axios/axios axios.get("uri") .then((response) => { dispatch({type: "REC_USER", name:response.data}) }) .catch((err) => { dispatch({type: "REC_USER_ERR", name:err}) }) //Do Async here and dispatch something else })
Actions:
This is a plain JavaScript object with TYPE(mostly as String). The state is read only; the only way to change is DISPATCH an ACTION. If we need to change the state in an application, then the only way is to emit an Action (An object describing what happened).
Action – It is an object and it always requires TYPE
var myAction = { type: "SET_NAME", name: "Fazil" }
Other best way to mention your action is, by using export function, like below
export function setUserName(name) { return { type: 'SET_NAME', name: name, } }
Reducer:
Once the Action is emitted, reducer will take action along with old state and do some manipulation and then returns new state.
Old state + Action = New State
var userReducer = function(state, action) { switch(action.type){ case "CHANGE_NAME" : { //state.name = action.name; - Wrong way to mention bcz here we're mutating the state state = {...state, name: action.name}; //state = {...backup, only_Change_that_Value} break; } case "CHANGE_COUNTRY" : { state = {...state, COUNTRY: action.country}; break; } default : return state; } return state; }
Even we can return same old state if the nothing is done. We can define any number of reducers we want and we can use the function in redux which helps to combine all the reducers,
const completeReducers = combineReducers({ user: userReducer, comments: commentsReducer });
One reducer can call other reducer as a delegate. When creating new state it won’t duplicate all the values in the object instead it will keep reference from the previous version of the state and it updates only the value which changes. This makes redux fast and utilize memory efficiently.
There are lot more useful functionalities available in Redux, for a beginner these are important to know. In my next article we will see how we can utilize Redux in React application which gives great benefit on managing States of the React Application. Stay tuned
Happy Coding
Ahamed
Leave a comment