Introduction
We’ll make a simple Todo-list app that performs all four CRUD (Create, Read, Update, Delete) operations- on the front-end, using React and Redux-Toolkit: live link
If you are familiar with Redux you can jump straight to the Implementation
What to get in this article:
Why Redux?
Redux is a state management library, that helps centralize your application’s state and logic. It comes with a DevTool which makes it easy to trace when, where, why and how your application’s state changed.
It works with any UI layer and popularly used with Reactjs.
And you might be wondering, what’s the difference between Redux and Redux-Toolkit, let’s take a look at that.
Redux vs ReduxToolkit
Redux is the core library for managing application state, while Redux-Toolkit is a companion library that provides additional utilities for working with Redux. You can use Redux on its own, but many developers find that Redux-Toolkit makes it even easier and more efficient to work with Redux even the Redux team recommends Redux-Toolkit as the approach for writing Redux logic, because it is a newer library that provides a set of utilities for working with Redux. It provides a simpler API for common tasks, as well as performance optimizations that can help to improve the performance of your application for example, the library uses Immer under the hood to provide immutable updates to the store, which can help to avoid unnecessary re-renders. Redux-Toolkit comes with functions for creating and managing Redux stores, as well as middleware for handling asynchronous actions, this can help to make your code more organized and maintainable.
Simply put, Redux-Toolkit is designed to make it easier and more efficient to write Redux applications
How Redux works
In Redux, you basically create an action and dispatch the action using the usedispatch hook.
Redux provides a predictable state container that helps manage the state of your application in a centralized manner, a store. A “store” is a container that retains your application’s global state, each component can access the store without having to send down props from one component to another.
The five major terminologies in Redux:
In major Redux applications you’ll find these major components working hand in hand. I will give brief explanation of each of these terminologies, it might not be clear enough, but follow through, while building our app it will become clearer. We’ll briefly discuss the main terminologies in a typical Redux app
Store: A single source of truth that holds the entire state tree of your application.
Actions: Actions are the medium used to send data from your application to your Redux store, they are plain JavaScript objects that represent an intention to change the state, they contain a type property that describes the action as well as a payload (an additional data necessary to carryout the action) to update the state.
Reducers: Reducers are Pure functions that take the current state and an action and return a new state. They should not modify the current state directly, but instead return a new state object.
Dispatch: To update the state, an action must be dispatched to the store using the `dispatch` function. This triggers the store to call the corresponding reducer function with the current state and the dispatched action. Just think of the `dispatch` function as `setState`
Selector: To access data from the store. We do this by using the `useSelector` hook from react-redux
Just think of Dispatch and Selector as
const [name, setName] = useState("Grey");
// Dispatch (update the state)
setName("Dan");
// Selector (get the state)
console.log(name)
Implementation
Installation
To get started, you only need two npm packages
npm install @reduxjs/toolkit react-redux
Create a Redux Store
src/redux/store.js
import { configureStore } from '@reduxjs/toolkit';
export const store = configureStore({
reducer:{},
});
Add the Redux Store to Index.js parent file
src/index.js
import { Provider } from 'react-redux';
import { store } from './redux/store';
<Provider store={store}>
<App />
</Provider>
When done importing these necessary components, ensure to wrap your component with the provider and include the store you added recently, this enables your whole app to access the Redux store
Create a Slice
Of course, Redux- Toolkit introduced slice. A slice is a part of the application’s state that can be updated independently. It contains a set of actions and a reducer that handles those actions. Think of a slice as a certain feature you want to apply different action to it, on different occasions, now each action in the feature (slice) uses the same state, having initial value of initialState
. In this app, I have 3 actions running in the same slice. All the actions reside in the reducers object
src/redux/reducer.js
import { createSlice } from '@reduxjs/toolkit';
const initialState = [];
const todoReducer = createSlice({
name: 'todos',
initialState,
reducers: {};
});
export const reducer = todoReducer.reducer;
With this, we can go ahead to add our slice Reducers to the store in src/redux/store.js
import { configureStore } from '@reduxjs/toolkit';
+ import { reducer } from './reducer';
export const store = configureStore({
+ reducer: reducer,
});
This is the basic configuration needed using Redux-toolkit, we are ready to go Redux baby!
Let’s go about creating actions in src/redux/reducer.js
To Add Note
import { createSlice } from '@reduxjs/toolkit';
const initialState = [];
const todoReducer = createSlice({
name: 'todos',
initialState,
reducers: {
+ // Adding new todo
+ addTodo: (state, action) => {
+ return [...state, action.payload];
+ },
},
});
+ export const { addTodo} = todoReducer.actions;
export const reducer = todoReducer.reducer;
The state
is the current state, with initial value of initialState
, action.payload is the value passed into the addTodo function in src/components/TextField/TextField.jsx
We use our actions to work with the store with the help of the useDispatch hook from react-redux, this is how we Dispatch as explained earlier
src/components/TextField/TextField.jsx
import { addTodo } from '../../redux/reducer';
import { useDispatch } from 'react-redux';
const dispatch = useDispatch();
dispatch(
addTodo({
id: Math.floor(Math.random() * 100),
item: text,
})
The addTodo
action takes in the value passed in, which is an object of two key: value pairs and adds it to the array, hence updating the state. Therefore making the state an array of objects with two keys: id and text.
To Delete Note:
import { createSlice } from '@reduxjs/toolkit';
const initialState = [];
const todoReducer = createSlice({
name: 'todos',
initialState,
reducers: {
// Adding new todo
addTodo: (state, action) => {
return [...state, action.payload];
},
+ deleteTodo: (state, action) => {
+ return state.filter((item) => {
+ return item.id !== action.payload;
+ });
+ },
},
});
+ export const { addTodo, deleteTodo} = todoReducer.actions;
export const reducer = todoReducer.reducer;
The deleteTodo
function checks for a matching id to the one passed in through our dispatch function, to update the state, while removing the matched id from the array
Here, the action.payload
is id
from src/components/Note/Note.jsx
import { deleteTodo } from '../../redux/reducer';
import { useDispatch } from 'react-redux';
const dispatch = useDispatch();
dispatch(deleteTodo(id));
Update Note:
updateTodo: (state, action) => {
return state.map((todo) => {
const item = todo.item;
if (todo.id === action.payload.id) {
return {
...todo,
[item]: action.payload.text,
};
}
return todo;
});
},
The updateTodo
function updates the value of a selected item from the array of objects(different list items), then updates it’s item
value by the text.
This function takes an object of two key value pairs as seen in src/components/Note/Note.jsx
import {updateTodo } from '../../redux/reducer';
updateTodo({ id, text: inputRef.current.value });
The id
is a numeric value used to identify an item from the list, the text is a string used to update the text of the identified item.
Access the state
This is where selector comes in, as explained earlier we use it by using the useSelector
hook from react-redux
. It helps us extract data from the Redux store state, using a selector function
import { useSelector } from 'react-redux';
import Note from '../Note/Note';
function ShowTodo() {
const list = useSelector((state) => state);
return (
<>
{list &&
list.map((item) => (
<Note text={item.item} key={item.id} id={item.id} />
))}
</>
);
}
export default ShowTodo;
And that is how we access data from our store.
Hope you got value!
Top comments (0)