Redux Toolkit With Typescript: How to Get Started
Learn how to use Redux with Typescript to set up production-level state management for web applications.
Join the DZone community and get the full member experience.
Join For FreeIf you're a React developer, chances are you already know how complicated it can get when working with global/shared states. Nonetheless, nowadays, there are two main ways to use this concept:
- Redux
- Context API.
It is essential to highlight that a learning curve is necessary to use both of these approaches in the best way possible. This view is based on the fact that its high complexity and verbosity come into focus whenever Redux is mentioned. This is even more pronounced when it comes to using Redux with Typescript.
However, in this article, the focus is on the Redux Toolkit, an official Redux library that makes it easy to configure and use all the resources offered by Redux. Suppose you've ever found Redux to be boring and challenging, I'm sure the explanations and examples I provide on how to implement Redux Toolkit with Typescript in React will help you reassess your position on the subject.
Table of Contents
- What is Redux?
- What is Typescript?
- What is Redux Toolkit?
- Why Redux Toolkit?
- Getting started with Redux Toolkit
- Conclusion
What Is Redux?
Redux is an open-source JavaScript library for managing and centralizing the application state. It is most commonly used with libraries such as React or Angular for building user interfaces. Similar to (and inspired by) Facebook's Flux architecture.
What Is Typescript?
TypeScript is an open-source programming language developed by Microsoft. It is a strict syntactic superset of JavaScript and adds optional static typing to the language. Types provide a way to describe the shape of an object, providing better documentation and allowing TypeScript to validate that your code is working correctly. Since TypeScript is a superset of JavaScript, existing JavaScript programs are also valid TypeScript programs.
What Is Redux Toolkit?
Redux Toolkit is the official Redux tool, opinionated, with batteries for efficient Redux development. It includes several utility functions that simplify the most common use cases of Redux, including:
- Store configuration.
- Setting dimmers.
- Immutable update logic.
You can also use it to create entire "slices" of state at once without writing any action creators or type of action manually.
Apart from the use cases, It also includes the most used Redux add-ons, such as Redux Thunk for asynchronous logic and Reselect for writing selector functions, such that you can use them right away. Essentially, the Redux Toolkit is intended to be the standard way of writing Redux logic, and it is highly recommended that you use it.
Why Redux Toolkit?
Firstly, the Redux Toolkit makes it easy to write good Redux applications. Additionally, it speeds up development by:
- Emphasizing adherence to best practices.
- Providing good default behaviours.
- Detecting errors.
- Making it easy to write simpler code.
Overall, the Redux Toolkit is beneficial to all Redux users, regardless of skill level or experience. This goes for whether you are a new Redux user setting up your first project or an experienced one who wants to simplify an existing application.
Getting Started With the Redux Toolkit
In this section, we will look at two main scenarios:
- Implementation within an existing project.
- Creating a new project.
1). Implementation Within an Existing Project
Step I
Add dependencies to your project:
npm install @reduxjs/toolkit react-redux
yarn add @reduxjs/toolkit react-redux
Step II
After the dependencies are installed, create a file for your Redux Store. Ex: src/store/index.ts
Within this file, you must use the “configureStore” function of the Redux Toolkit to create your store and later export it.
Note; configureStore: Function that provides simplified configuration options to combine all your reducers or add any middleware.
import {
configureStore
}
from '@reduxjs/toolkit
Step III
Provide the Redux Store to React:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { store } from './store';
import { Provider } from 'react-redux';
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
Step IV
To create your reducers, use the Redux Toolkit's createSlice function.
You will need to set three properties in this function: name, initialState, and reducers.
- name: Used in action types (String)
- initialState: Initial state for the respective reducer (any)
- reducers: An object of reducer functions. Key names will be used to generate actions.(Object<string, function>)
Redux Toolkit allows us to write "mutating" logic in reducers. However, it doesn't actually mutate the state because it uses the Immer library, which detects changes to a "draft state" and produces a brand new immutable state based on those changes:
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
export interface CounterState {
value: number
incrementAmount: number
}
const initialState: CounterState = {
value: 0, incrementAmount : 1
}
export const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
state.value += state.incrementAmount
},
decrement: (state) => {
state.value -= state.incrementAmount
},
changeIncrementAmount: (state, action: PayloadAction<number>) => {
state.incrementAmount = action.payload
},
},
})
export const { increment, decrement, changeIncrementAmount } = counterSlice.actions
export default counterSlice.reducer
Step V
After creating the reducer, add it to the store:
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './counterReducer'
export const store = configureStore({
reducer: {
counter: counterReducer,
},
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
Step VI
After that, you can use the redux state and Actions inside your components.
To read the data, use the "useSelector" function, and for dispatch actions, use the "useDispatch" function:
import { useSelector, useDispatch } from "react-redux";
import { RootState } from "./store";
import { increment, decrement, changeIncrementAmount, } from "./store/counterReducer";
function App() {
const count = useSelector((state: RootState) => state.counter.value); const dispatch = useDispatch();
const incrementAmount = useSelector(
(state: RootState) => state.counter.incrementAmount
);
function handleChange(incrementAmountValue: string) {
dispatch(changeIncrementAmount(Number(incrementAmountValue)));
}
return (
Counter
dispatch(decrement())}>
-
{count}
dispatch(increment())}>
+
Change Increment Amount
handleChange(e.target.value)}
/>
);
}
export default App;
2). Creating a New Project
Creating a new project with Redux Toolkit is very simple. All you need to use is this command:
npx create-react-app APPLICATION_NAME --template redux-typescript
Behind the scenes, the CRA will be used to create your React application. In the end, you will have a similar structure to this:
── src
── app
── hooks.ts
── store.ts
── Features
── counter
── counter.module.css
── counter.tsx
── counterAPI.ts
── counterSlice.spec.ts
── counterSlice.ts
- app/hooks.ts: While you can import RootState and AppDispatch types for each component, it's better to create typed versions of the “useDispatch” and “useSelector” hooks for use in your application. This allows you to import them into any component files that need to use the hooks and avoids potential circular import dependency issues.
- app/store.ts: To use the "configureStore" function, no extra typing is required. However, you will want to use RootState and Dispatch typing inside files that will need this reference. Therefore, these definitions are created and exported within the store.ts file.
- features/counter/counter.module.css: Simply the file of the stylizations of the component created.
- features/counter/counter.tsx: Main component file, where dispatch functions triggers and global state values are used. In addition to all Html structures being present inside it.
- counterAPI.ts: Inside is a dummy function to mimic an asynchronous data request.
- counterSlice.spec.ts: File where tests are created for the component’s main features.
- counterSlice.ts: The location where reducers and actions are defined and all the logic to manage the global state and control so that data consistency is always maintained
Conclusion
Redux Toolkit is an excellent tool to give productivity to applications that use Redux, and together with Typescript, your applications will be reliable and easy to maintain.
As much as everything can be built only with Redux, the complexity and verbosity make the development slower and require a greater learning curve.
Published at DZone with permission of Pedro Silva. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments