Introduction
Redux is a state container for Javascript apps. It serves as a library within React Apps but can also be associated with other Javascript frameworks.
Redux supports the development of large and complex applications that may need to take advantage of this container.
Redux is based on three fundamental concepts:
- reducers
- actions
- action creators
- store
Reducers
A reducer is a function that uses the previous state and an action as input and returns a new state as output. An action is an object with a type and an optional payload.
Here is an example of a Reducer:
function Reducer(previousState, action) => {
// use the action type and payload to create a new state based on
// the previous state.
return newState;
}
Reducers allow you to specify how the state of applications changes in response to the actions deployed in the store.
If your app has multiple states, it can also have multiple reducers. The core functionality of your app should have its own reducer..
Action
An action is a simple Javascript object that represents the load of information that is sent from the application to your store. Each action has a type and an optional payload.
Major changes in applications using redux start with an event that is directly or indirectly triggered by a user. Events, such as clicking on a button, selecting objects or hovering the cursor over a particular element, trigger AJAX requests that send back some data. There are endless possibilities to associate an action as a response to an event.
Actions are created by an action creator.
ActionCreator
In Redux, an action creator is a feature that returns an action object. It may seem unnecessary but creators allow you to send an action object to all the different reducers in the app, ensuring a benefit in terms of portability and testing.
Depending on the action sent, reducers can return a new version of their state, which is passed into the application state and, finally, into the React app, by reloading the components.
According to the definition given by Action Creator, the function may have a syntax similar to the following:
export function newTask({ task }) {
return {
type: 'NEW_TASK',
payload: {
task,
completed: false
},
}
}
// esempio di valore di ritorno:
// {
// type: 'NEW_TASK',
// todo: { task: 'Prepara valigia viaggio', completed: false },
// }
Example of an interaction between a reducer and an action of type NEW_TASK:
export default function(state = initialState, action) {
switch (action.type) {
case 'NEW_TASK':
const newState = [...state, action.payload];
return newState;
default:
return state;
}
}
Depending on the involvement in the action, reducers will either return the same state as before or a new one. All reducers will process the action but only some of them will change their state.
Finally, the components will be rendered again:
{
currentTask: { task: 'Prepara valigia viaggio', completed: false },
todos: [
{ task: 'Prepara valigia viaggio', completed: false },
{ task: 'Lascia cane alla pensione', completed: true }
],
}
Combining Reducers
Redux ensures you the combineReducers feature to perform two tasks:
- Generate a function that calls our reducers with the portion of the state selected based on their key.
- Then combine the results back into one object.
The Store
The store is the object that includes the actions and reducers. Basically, it manages information about what is happening and state changes in response to those events.
The tasks of the store are:
- Permission to access via getState()
- Permission to update a state via dispatch(action)
- Maintenance of the state of the entire application
- Registration listeners via subscribe(listener)
- Deregistrationlistenersvia the function returned by subscribe(listener)
To create a store, simply pass it a combination of reducers and then allow it to deploy actions.
import { createStore } from 'redux';
import todoReducer from './reducers';
const store = createStore(todoReducer);
store.dispatch(addTodo({ task: 'Finisci di leggere la guida'}));
store.dispatch(addTodo({ task: 'Applica i concetti imparati su un tuo progetto!' }));
//...
Data Flow in Redux
Redux has a fixed one-way data flow, which allows you to better understand the data lifecycle within your application.
The data lifecycle steps in Redux are as follows
export default const currentTask(state = {}, action){
// deal with this piece of state
return newState;
};
export default const todos(state = [], action){
// deal with this piece of state
return newState;
};
export default const todoApp = combineReducers({
todos,
currentTask,
});
- An event within your application triggers a call to store.dispatch(actionCreator(payload))
- The store calls the root reducer with the current state and action
- The root reducer combines the output of several reducers into a single state tree
Once the action is issued, todoApp will call both reducers and combine the result sets into a single state tree:
return {
todos: nextTodos,
currentTask: nextCurrentTask,
};
Once Redux saves the state tree, the new state tree will be the next in your app.
Conclusions
By the end of this guide, you'll have completed your smattering of Redux. Delve into the concepts learned and many more withthe Redux Official Documentation.