Lesson 78 of 60 – TypeScript with Redux Toolkit
100%

TypeScript with Redux Toolkit

Redux Toolkit is the recommended way to write Redux logic in modern React and React Native applications. When TypeScript is used with Redux Toolkit, we can create strongly typed state, actions, reducers, selectors, and dispatch functions.

In this lesson, we will learn how to configure a Redux store, create slices, define state interfaces, use typed hooks, dispatch actions, read state, and connect Redux Toolkit with a React Native application.

Note: Redux Toolkit simplifies Redux development by providing tools such as configureStore() and createSlice().

1. What is Redux?

Redux is a state management library that provides a centralized store for application state.

Instead of passing the same data through many components, different components can access shared state from the Redux store.

2. What is Redux Toolkit?

Redux Toolkit is a collection of tools that makes Redux easier to configure and use.

  • configureStore()
  • createSlice()
  • createAsyncThunk()
  • Redux middleware configuration

3. Installing Redux Toolkit

Install Redux Toolkit and React Redux in a React Native project:

npm install @reduxjs/toolkit react-redux

These packages provide Redux functionality and React bindings.

4. Creating a State Interface

interface CounterState {
    value: number;
}

const initialState: CounterState = {
    value: 0
};

The interface describes the structure of the Redux state.

5. Creating a Slice

import {
    createSlice
} from "@reduxjs/toolkit";

const counterSlice =
    createSlice({
        name: "counter",
        initialState,
        reducers: {}
    });

A slice contains a section of application state and the reducers that update that state.

6. Adding Reducers

const counterSlice =
    createSlice({
        name: "counter",
        initialState,

        reducers: {

            increment: (
                state
            ) => {

                state.value += 1;

            }

        }
    });

7. Exporting Slice Actions

export const {
    increment
} = counterSlice.actions;

Redux Toolkit automatically creates action creators for reducers defined inside the slice.

8. Exporting the Reducer

export default
    counterSlice.reducer;

The generated reducer is added to the Redux store.

9. Creating the Redux Store

import {
    configureStore
} from "@reduxjs/toolkit";

import counterReducer
    from "./counterSlice";

export const store =
    configureStore({

        reducer: {
            counter:
                counterReducer
        }

    });

10. Getting RootState Type

export type RootState =
    ReturnType<typeof store.getState>;

RootState represents the complete state structure of the Redux store.

11. Getting AppDispatch Type

export type AppDispatch =
    typeof store.dispatch;

This type represents the dispatch function provided by the Redux store.

12. Providing the Redux Store

import {
    Provider
} from "react-redux";

import {
    store
} from "./store";

<Provider store={store}>

    <App />

</Provider>

The Provider makes the Redux store available to components below it.

13. Using useSelector

import {
    useSelector
} from "react-redux";

const count =
    useSelector(
        (state: RootState) =>
            state.counter.value
    );

useSelector() reads data from the Redux store.

14. Using useDispatch

import {
    useDispatch
} from "react-redux";

const dispatch =
    useDispatch<AppDispatch>();

dispatch(increment());

The typed dispatch function can safely dispatch Redux actions.

15. Creating Typed Hooks

import {
    useDispatch,
    useSelector
} from "react-redux";

export const useAppDispatch =
    useDispatch.withTypes<AppDispatch>();

export const useAppSelector =
    useSelector.withTypes<RootState>();

Typed hooks can make Redux usage cleaner across the application.

16. Reading State with a Typed Hook

const count =
    useAppSelector(
        state =>
            state.counter.value
    );

TypeScript knows the structure of the Redux state through RootState.

17. Dispatching an Action

const dispatch =
    useAppDispatch();

dispatch(increment());

The component dispatches the action generated by the counter slice.

18. Action Payloads

reducers: {

    incrementBy: (
        state,
        action: PayloadAction<number>
    ) => {

        state.value += action.payload;

    }

}

PayloadAction<number> tells TypeScript that the action payload must be a number.

19. Dispatching with a Payload

dispatch(
    incrementBy(5)
);

The payload is passed to the generated action creator.

20. User State with Redux Toolkit

interface User {
    id: number;
    name: string;
    email: string;
}

interface UserState {
    user: User | null;
}

const initialState:
    UserState = {
        user: null
    };

21. User Slice

const userSlice =
    createSlice({

        name: "user",

        initialState,

        reducers: {

            setUser: (
                state,
                action:
                    PayloadAction<User>
            ) => {

                state.user =
                    action.payload;

            },

            clearUser: (
                state
            ) => {

                state.user = null;

            }

        }

    });

22. Redux with React Native Screens

function ProfileScreen():
    React.JSX.Element {

    const user =
        useAppSelector(
            state =>
                state.user.user
        );

    return (
        <View>

            <Text>
                {user?.name}
            </Text>

        </View>
    );
}

A React Native screen can read Redux state using a typed selector.

23. Common Redux TypeScript Mistakes

  • Using any for Redux state.
  • Not defining a state interface.
  • Forgetting to type action payloads.
  • Using an incorrect RootState type.
  • Using an untyped dispatch in complex applications.
  • Reading incorrect state properties.
  • Putting unrelated state into one large slice.

24. Best Practices

  • Create interfaces for important state objects.
  • Use configureStore() to create the store.
  • Use createSlice() for Redux logic.
  • Type action payloads with PayloadAction.
  • Export RootState and AppDispatch.
  • Use typed Redux hooks.
  • Keep related state and reducers inside appropriate slices.

25. Redux vs Context API

Context API is useful for sharing relatively simple application-wide values such as themes or user information.

Redux Toolkit provides a structured state management system with actions, reducers, middleware, selectors, and a centralized store.

The choice depends on the application's requirements and complexity.

26. Redux Project Structure

src/
    app/
        store.ts
        hooks.ts

    features/
        counter/
            counterSlice.ts

        user/
            userSlice.ts

    screens/
        HomeScreen.tsx
        ProfileScreen.tsx

Organizing Redux code by features can make larger applications easier to maintain.

27. Complete Store and Slice Example

// counterSlice.ts

import {
    createSlice,
    PayloadAction
} from "@reduxjs/toolkit";

interface CounterState {
    value: number;
}

const initialState:
    CounterState = {
        value: 0
    };

const counterSlice =
    createSlice({

        name: "counter",

        initialState,

        reducers: {

            increment: (
                state
            ) => {

                state.value += 1;

            },

            decrement: (
                state
            ) => {

                state.value -= 1;

            },

            incrementBy: (
                state,
                action:
                    PayloadAction<number>
            ) => {

                state.value +=
                    action.payload;

            }

        }

    });

export const {
    increment,
    decrement,
    incrementBy
} = counterSlice.actions;

export default
    counterSlice.reducer;


// store.ts

import {
    configureStore
} from "@reduxjs/toolkit";

import counterReducer
    from "../features/counter/counterSlice";

export const store =
    configureStore({

        reducer: {

            counter:
                counterReducer

        }

    });

export type RootState =
    ReturnType<typeof store.getState>;

export type AppDispatch =
    typeof store.dispatch;

28. Complete React Native Example

import React from "react";

import {
    View,
    Text,
    Button
} from "react-native";

import {
    useAppDispatch,
    useAppSelector
} from "../app/hooks";

import {
    increment,
    decrement
} from "../features/counter/counterSlice";

export default function CounterScreen():
    React.JSX.Element {

    const count =
        useAppSelector(
            state =>
                state.counter.value
        );

    const dispatch =
        useAppDispatch();

    return (
        <View>

            <Text>
                Count: {count}
            </Text>

            <Button
                title="Increase"
                onPress={() =>
                    dispatch(increment())
                }
            />

            <Button
                title="Decrease"
                onPress={() =>
                    dispatch(decrement())
                }
            />

        </View>
    );
}

The screen reads typed Redux state and dispatches typed actions.

29. Benefits of Redux Toolkit with TypeScript

  • Centralized application state.
  • Strongly typed state.
  • Typed actions and payloads.
  • Better code completion.
  • Safer state updates.
  • Reusable typed hooks.
  • Good structure for larger React Native applications.
  • Easier maintenance of complex state logic.

30. Summary

Redux Toolkit provides a structured way to manage shared application state in React Native. TypeScript adds type safety to the store, state objects, actions, reducers, selectors, and dispatch functions.

You should now understand Redux Toolkit installation, state interfaces, slices, reducers, actions, payloads, the Redux store, RootState, AppDispatch, typed hooks, React Native integration, and project organization.

📌 Key Points

  • Redux Toolkit simplifies Redux development.
  • Use configureStore() to create the store.
  • Use createSlice() to create state logic.
  • Define TypeScript interfaces for Redux state.
  • Use PayloadAction to type action payloads.
  • Create RootState and AppDispatch types.
  • Use typed hooks to read and update Redux state.
  • Redux Toolkit can be used effectively in React Native applications.

🧠 Quick Quiz

Question: Which Redux Toolkit function is commonly used to create a slice of state with reducers and actions?