A complete React Redux store implementation with TypeScript

If you are new to React and wanted to share data and manage your application state between your components navigation, Redux could be one of the choices. 

Redux can maintain an application state in single immutable object, which can't be modified directly. Only using Action Reducers can modify the object and returns a new object. 

In this article, I am going to create a simple application with React, Redux, and TypeScript. Let's begin the journey...

redux-react-typescript-router


Step One: React TypeScript Project creation and npm library installation and Route configuration

Create yours react typescript project with SCSS support.

npx create-react-app redux-demo-app --template typescript

npm install --save @types/react-router-dom

Now Adding Bootstrap and SCSS

npm install --save bootstrap react-bootstrap 

npm install --save node-sass

Open style.scss file and import bootstrap library reference.

@import "~bootstrap/scss/bootstrap";

 

Now configure the route to your application. I have a very simple 3 page, Dashboard, Profile, and About. 

redux-react-typescript-router-folder-structure redux-react-typescript-router-folder-structure

The header component is having a navigation bar and links to different pages. I am using lazy loading to load the different components to respective routes. 

 

 


Step 2: Create a User form component to save or populate user data for update

Now I am going to create a User form to take inputs from users. Created a custom hook to save or update user data and return the modified object to the component. 

  • Create a User model and have dropdown menu data source. (User.ts)

export interface User {

id: number;

name: string | undefined;

role: string | undefined;

organization: string | undefined;

}

 

export const userRoleDaraSource = [

{ roleName: 'FrontEnd Developer', id: "1"},

{ roleName: 'QA', id: "2"},

{ roleName: 'DevOps', id: "3"},

{ roleName: 'BackEnd Developer', id: "4"},

{ roleName: 'Data Engineer', id: "5"}

];

 

  • User form hook creation 
 

const useFormField = (user: User) => {

const [formFields, setFormFields] = useState<User>(user);

 

// update or save user data 

const createChangeHandler = (key: keyof User) => (e: ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {

const value = e.target.value;

setFormFields((prev: User) => ({ ...prev, [key]: value }));

}

 

// reset user form 

const resetFormHandler = () => {

for (const [key] of Object.entries(user)) {

setFormFields((prev: User) => ({ ...prev, [key]: (key !== 'id') ? '' : 0 }));

}

}

 

return { formFields, setFormFields, createChangeHandler, resetFormHandler };

}

 

  • Populate user form by selecting any of user from the list

useEffect(() => {

if (props.userDetails.id) {

setFormFields(props.userDetails);

}

}, [props.userDetails])

 

 


Step 3: Create User List Component with Edit and Delete button

User List component will take input an array of users and expose two method as a props. 

type Props = {

userList: User[] | undefined,

removeUser: (arg: User) => void;

editUser: (arg: User) => void;

}

 

 

UserList.tsx code.


Step 4: Redux npm library installation and folder structure

You need to install the following npm libraries to get supports for Redux configuration. 

 npm install --save react-redux redux redux-thunk @types/react-redux @types/redux @types/redux-thunk

 

After installation, you need to create the below files for Action, Reducers, and Store, have a closure look for folder structure.

redux-react-typescript-folder-structure

ActionCreators.ts - Actions send data from the application (user interactions, internal events such as API calls, and form submissions) to the store.

ActionTypes.ts - List of Action types 

UserReducers.ts - Based on defined action, it updated the store with a new object and maintain the Object tree.

Store.ts - create a store and save store data to session storage to handle browser refresh

 

types.d.ts - define the types for Action & dispatch


Step 5: Inject Store Object to React application

Now you need to inject the store object into your React Application. As I am going to use the store across the application, so it's being injected at the top container. Here is the reference. 


Step 6: Save data to Redux Store

Now as the store is ready to use, I am going to save data to the store from user input and also populate the form with an existing objects. 

 


Step 7: Fetch data from Redux Store

There are two way you can access the store data. You can use useSelector hook or use connect method to get data from store. 

const usersListArray: User[] = useSelector((state: UserState) => state.users, shallowEqual);

const [usersList, setUsersList] = useState<User[]>(usersListArray);

 

Or you can use connect method to get state data.

const mapState = (state: any) => ({

usersList: state.users

})

 

const mapDispatch = {

deleteUser: (user: User) => (

removeUser(user)

),

updateUser: () => {}

}

 

export default connect<StateProps, DispatchProps>(mapState, mapDispatch)(About);

 

 

Using useSelector hook. 

Profile.tsx 

Using connect method.

About.tsx


Live Demo

Happy Coding!