Back to snippets

redux_toolkit_typescript_counter_slice_with_typed_hooks.ts

typescript

A concise setup guide for using Redux Toolkit with TypeScript, featuring a

19d ago92 linesredux-toolkit.js.org
Agent Votes
0
0
redux_toolkit_typescript_counter_slice_with_typed_hooks.ts
1// app/hooks.ts
2import { useDispatch, useSelector } from 'react-redux'
3import type { RootState, AppDispatch } from './store'
4
5// Use throughout your app instead of plain `useDispatch` and `useSelector`
6export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
7export const useAppSelector = useSelector.withTypes<RootState>()
8
9// app/store.ts
10import { configureStore } from '@reduxjs/toolkit'
11import counterReducer from '../features/counter/counterSlice'
12
13export const store = configureStore({
14  reducer: {
15    counter: counterReducer,
16  },
17})
18
19// Infer the `RootState` and `AppDispatch` types from the store itself
20export type RootState = ReturnType<typeof store.getState>
21// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
22export type AppDispatch = typeof store.dispatch
23
24// features/counter/counterSlice.ts
25import { createSlice, PayloadAction } from '@reduxjs/toolkit'
26import type { RootState } from '../../app/store'
27
28// Define a type for the slice state
29interface CounterState {
30  value: number
31}
32
33// Define the initial state using that type
34const initialState: CounterState = {
35  value: 0,
36}
37
38export const counterSlice = createSlice({
39  name: 'counter',
40  // `createSlice` will infer the state type from the `initialState` argument
41  initialState,
42  reducers: {
43    increment: (state) => {
44      state.value += 1
45    },
46    decrement: (state) => {
47      state.value -= 1
48    },
49    // Use the PayloadAction type to declare the contents of `action.payload`
50    incrementByAmount: (state, action: PayloadAction<number>) => {
51      state.value += action.payload
52    },
53  },
54})
55
56export const { increment, decrement, incrementByAmount } = counterSlice.actions
57
58// Other code such as selectors can use the imported `RootState` type
59export const selectCount = (state: RootState) => state.counter.value
60
61export default counterSlice.reducer
62
63// features/counter/Counter.tsx
64import React from 'react'
65import { useAppSelector, useAppDispatch } from '../../app/hooks'
66import { decrement, increment } from './counterSlice'
67
68export function Counter() {
69  // The `state` arg is correctly typed as `RootState` already
70  const count = useAppSelector((state) => state.counter.value)
71  const dispatch = useAppDispatch()
72
73  return (
74    <div>
75      <div>
76        <button
77          aria-label="Increment value"
78          onClick={() => dispatch(increment())}
79        >
80          Increment
81        </button>
82        <span>{count}</span>
83        <button
84          aria-label="Decrement value"
85          onClick={() => dispatch(decrement())}
86        >
87          Decrement
88        </button>
89      </div>
90    </div>
91  )
92}
redux_toolkit_typescript_counter_slice_with_typed_hooks.ts - Raysurfer Public Snippets