Integrating Redux in Ionic React typescript for state management

I seek out simple and scalable solutions to various challenges with tech
Search for a command to run...

I seek out simple and scalable solutions to various challenges with tech
In the process of doing business, I often encounter such a problem that I spend a lot of time managing various documents. Looking for solutions, I found a great article that you can read here at the link, and I think this is a really great option for how to optimize the company, so be sure to check this information.
Program to interfaces, not implementations.

ChatGPT is great for brainstorming, but professionals need structured drafts, consistent tone, and version history. Learn when to use ChatGPT vs a document-first AI writing assistant like WriterOS
Today I’m launching ProMind Writer, a focused product built around one simple reality: a huge number of professionals do not “write occasionally.” They write constantly. Proposals, SOPs, policies, PRD

How Every Layer You Add Changes Everything

Many SaaS companies face a common challenge: despite feature-rich products and aggressive marketing, they struggle with high churn rates. The root cause? A classic case of "feedback blindness" – building in isolation without truly understanding user ...

The first question that comes to mind is what is state? Think of state as the condition of your app at any specific time. It answers questions like:
Redux offers a predictable state container for javascript apps.
Assumptions
Start by installing Redux into your existing ionic-react app:
npm install --save redux
npm install --save react-redux
For the purpose of structure and maintainability, we would be taking an opinionated approach and hence be installing redux toolkit. Redux toolkit allows for easy debugging and helps in structuring your application store.
npm install --save @reduxjs/toolkit
npm i -D @types/react-redux
npm install --save-dev @types/webpack-env
The last command above helps fix an issue with webpack and module.hot as would be seen further down.
Our redux folder structure:
reducers/index.ts
import { combineReducers } from "@reduxjs/toolkit";
const rootReducer = combineReducers({});
export type RootState = ReturnType<typeof rootReducer>;
export default rootReducer;
This file serves as the single point of export of all the reducers.
The empty object in const rootReducer = combineReducers({}); would contain the reducers to be exported.
store.ts
import { configureStore } from "@reduxjs/toolkit";
import rootReducer from "./reducers";
const store = configureStore({
reducer: rootReducer
});
if (process.env.NODE_ENV === "development" && module.hot) {
module.hot.accept("./reducers", () => {
const newRootReducer = require("./reducers").default;
store.replaceReducer(newRootReducer);
});
}
export type AppDispatch = typeof store.dispatch;
export default store;
This handles creating the store as well as its initialization. The first block handles bootstrapping the store with the reducer. The second block handles hot reloading/ compiling, allowing re-importing the new version of the root reducer function whenever it's been recompiled. It also tells the store to use the new version instead.
We would be making changes to the index.ts file (Entrypoint to the app) to use the store.
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import store from "./store";
import * as serviceWorker from "./serviceWorker";
const render = () => {
const App = require("./App").default;
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
};
render();
if (process.env.NODE_ENV === "development" && module.hot) {
module.hot.accept("./App", render);
}
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
A provider is added to make the Redux store available to connect() calls in the component hierarchy.
We would be creating an action - reducer combination that controls a simple loading screen and alert dialog.
action/uiel.ts
import { createAction } from "@reduxjs/toolkit";
interface Loader {
isLoading: boolean;
}
interface Alert {
isVisible: boolean;
message: string;
}
export const setLoader = createAction("LOADER", function prepare(
loader: Loader
) {
return {
payload: loader
};
});
export const setAlert = createAction("ALERT", function prepare(alert: Alert) {
return {
payload: alert
};
});
reducers/uiel.ts
import { createReducer } from "@reduxjs/toolkit";
import { setLoader, setAlert } from "../actions/uiel";
const loader = {
isLoading: false
};
const alert = {
isVisible: false,
message: ""
};
export const UielReducer = createReducer(
{ loader, alert },
{
[setLoader.type]: (state, action) => ({
...state,
loader: { ...action.payload }
}),
[setAlert.type]: (state, action) => ({
...state,
alert: { ...action.payload }
})
}
);
In the createReducer method call, the first argument is a JSON object representing the initial state followed by a JSON of methods for mutation. The keys for these methods are gotten from the action types. A mutation takes the initial state and action which contains a payload as parameters.
With the action and reducer above, the reducer would be imported into reducers/index.ts in the combineReducers function call as seen below:
import { combineReducers } from '@reduxjs/toolkit';
import { UielReducer } from './uiel';
const rootReducer = combineReducers({
uiel: UielReducer
});
export type RootState = ReturnType<typeof rootReducer>;
export default rootReducer;
Now, we have Redux setup. Let's try dispatching some actions and getting values from the state. We would be creating a HomePage component.
components/HomePage.ts
import React from 'react';
import { connect } from 'react-redux';
import { setLoader } from '../actions/uiel';
const HomePage: React.FC = (props) => {
useEffect(() => {
setTimeout(() => props.dispatch(setLoader({ isLoading: true })), 2000);
},[])
return (
{props.isLoading?
<div>
<p>The page is loading... Please wait.</p>
</div> :
null
}
)
}
export default connect((props: any) => ({
isLoading: props.uiel.loader.isLoading
}))(HomePage);
The HomePage component's props is injected with {isLoading: props.uiel.loader.isLoading} and a dispatch object. Store value for loading can be retrieved by calling props.isLoading while an action can be dispatched by calling props.dispatch with an action passed in as a parameter as seen in the code snippet above.
If you need a website for your business, web or mobile application, head over to https://zhaptek.com and let's get talking or sign up as a referral and get 10% for every successful client referred. 😊
Leave comments below! 😊