React: Redux Toolkit
Theory: Slices
Let's start diving into Toolkit by looking at slices from the main point. Whatever we do inside slices, they generate the usual reducers and actions, which we pass to Redux.
In other words, slices do not add any new features to Redux. They automate routines, reduce the amount of code, and provide more convenient handles for controlling actions and states.
Let us create a slice. We need at least three components — a name, an initial state, and a set of reducers:
Name
We use the name as a prefix when naming the action. In the picture to the left, you see the Navigation. It helps to debug by showing us where the action came from:
Initial state
The initial state refers to the underlying data structure and some initial data, if any. It can be the value 0 for a counter, for example. Note that the initial state does not include data you pump out via the API. We fill them in later through actions.
Reducers
Reducers in Toolkit are similar to those in Redux but with some differences. Each reducer corresponds to a specific action, so there's no switch construction inside, and the reducers themselves are very small. And there is a direct change of state within the Reducers. How is that possible?
Despite the conceptual beauty and purity of Redux, it becomes inconvenient to work with when a state is deeply nested. The prohibition of direct changes generates complex constructions. We have to write them to update deeply hidden data:
There are many libraries in JavaScript to solve this problem, but they all require learning another tool. This tool reduces the amount of code but introduces another level of abstraction with all its challenges and complexities of use. It went on until the Immer appeared. This library allows you to trace direct changes within an object to update the original without mutations. In other words, we create a Redux-style copy:
Immer handles it like the reducers in Redux in an unchangeable style instead of directly changing the baseState.
Every reducer in Toolkit works like a callback from Immer, into which we pass the draft. Now we can mutate the state, but internally, everything works as if we didn't. This approach preserves all features of Redux, including its DevTool, the utility for analyzing what happens in the browser. And this is the best part. We get the perks of both worlds, keeping the entire Redux ecosystem intact.
And finally, exports. The createSlice() function generates a re-renderer and its actions. The official documentation recommends exporting reducers by default and actions by names:
Don't forget to add each new directory to the store:
Batch
In cases with several slices, you should update the state with several simultaneous actions. If you do it one by one, a component will be redrawn:
The code renders the Posts component whenever the state changes. It happens twice: when we add posts dispatch(addPosts(posts)) and when we add users dispatch(addUsers(users)).
In the first case, we have a problem. We cannot find the author since we have not added the users yet. To avoid this, we have a batch() function, which allows you to combine several state handlers:
In this case, when uploading posts and users and adding them to the table, the Posts component is rendered once — after we have added all the data. Note the internal function fetchData(). According to the documentation, we shouldn't declare the function passed to useEffect() as asynchronous, so we created an internal asynchronous function.

