I’ve been working with react-redux, and I’m loving it, working with react is awesome, but it can get confusing really fast, so when I was introduced to redux I just instantly loved it. The thing is… when I created an application using
yarn create ract-app --template redux
, the app had a different syntax than the one I was taught in all the tutorials I saw on youtube, so I started playing around with the default application, and the way they do things there is cleaner and more straight forward. After a quick google search, I realized the default app uses the @redux/toolkit and I wanted to talk about it because it’s pretty great, so…From the official GitHub repo: [@reactjs/toolkit] is the official, opinionated, toolset for react-redux, it’s intended to be the standard way to write Redux logic and it’s great at doing its job. It takes a lot of pieces of code that look weird (in my opinion), and make them make more sense.
In this article, I’m gonna go 1 by 1 on the APIs included on the toolkit and how to translate from the standard way to do them, as well as a little description of what that action is used for (in case anyone need a refresher 😉).
Just before I start, it’s important to say that this toolkit it completely compatible (as far as I know) with the regular syntax, so you can mix them.
The actions are the name of the ‘functions’ you are gonna call from the react app to interact with the redux store, they have the name that is gonna be switched on the reducer (we’ll talk about this later), and a payload if one is needed to change the state.
const createBook = book => {
type: 'CREATE-BOOK',
payload: book
};
const clearFilter = () => {
type: 'CLEAR_FILTER'
};
//then you can call them
createBook(book);
clearFilter();
This process can create long files, and it adds a lot of boilerplate. The toolkit uses
createAction
to automatically create the type and receive a single argument that becomes the action.payload
, it looks like this.import createAction from '@reduxjs/toolkit'
const createBook = createAction('CREATE_BOOK');
const clearFilter = createAction('CLEAR_FILTER');
// and the you call them
createBook(book);
clearFilter();
We can use the actions created this way when using createReducer but first let’s check what that is.
A reducer is the second half to interact with the redux store, if the action is the name, the reducer it’s the process the store is gonna take when it receives the action name, It confused me at the beginning too, but some code and practice solved that, so here we go, usually a reducer it’s a Switch where the action name is switched and then a process it’s started like this:
const bookReducer = (state = [], action) => {
switch (action.type) {
case 'CREATE_BOOK':
return [...state, action.payload.book];
case 'REMOVE_BOOK':
if (index === -1) {
return [...state];
}
return [ ...state.slice(0, index),
...state.slice(index + 1), ];
default:
return [...state]; }
};
The reducer accepts an initial state, in this case, an empty array, and then the action, from where we are gonna extract the type.
An important thing to mention is that a standard reducer like this requires you to make reducers where you don't modify the state itself, for example, you can’t make return state.splice(0,1), because splice modifies the array who’s calling it. This is not the case with createReducerbecause it uses immer by default, which lets you write mutative code. So we end up with a much simpler:
import { createReducer } from '@reduxjs/toolkit';
const bookReducer = createReducer( [], {
CREATE_BOOK: (state, action) => {state.push(action.payload);},
REMOVE_BOOK: (state, action) => {state.splice(action.payload, 1);}
});
Also as I mentioned before, if you created the action with
createAction
you can use them here with computed property syntax:import { createReducer, createAction } from '@reduxjs/toolkit';
const createBook = createAction('CREATE_BOOK')
const bookReducer = createReducer( [], {
[CREATE_BOOK]: (state, action) => { state.push(action.payload); },
});
This is a big one, with createSliceyou can sort of combine both create actions and create reducer in one big, easy to read (and understand) function, it’s beautiful to watch:
import { createSlice } from '@reduxjs/toolkit';
const bookStoreSlice = createSlice(){
name: 'bookStore',
initialState: []
reducers:{
createBook: (state, action) => { state.push(action.payload); },
removeBook: (state, action) => { state.splice(action.payload, 1);}
}
}
const { createBook } = bookStoreSlice.actions;
const bookReducer = bookStoreSlice.reducer;
//then just call it
createBook(book);
This piece of code creates the actions and reducers, awesome right?, The only thing we need now it’s a way to give this reducer to a store, and yes, the toolkit has a great way to do just this.
Usually, you can use createStore to well… create a store and use it in a provider, but if you have multiple reducers you will need to combine them, name them and then use them, like this:
import { combineReducers, createStore } from 'redux';
const rootReducer = combineReducers({
books: bookReducer,
filter: filterReducer,
});
const store = createStore( rootReducer, initialState,);
With the toolkit, you can combine these 2 functions in one, and also add the middlewares you need (this post is already too long, so I’m gonna talk about middlewares sometime later).
import { configureStore } from '@treactjs/toolkit';
const store = configureStore({
reducer: {
books: bookReducer,
filter: filterReducer
}
});
There’s a lot more in the Reactjs/toolkit, but just with these basics, and the ability to write readable code plus mutable code in the states, I just don’t see why not use the toolkit in new or already created applications.
The toolkit has an amazing documentation, and it’s maintained constantly. Thank you for taking the time to read this, and I hope it was somewhat useful. See you atthe next one.
Previously published at https://medium.com/@yosept.flores/from-react-redux-to-reduxjs-toolkit-42344c9d2832