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...
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.
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.
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"}
];
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 };
}
useEffect(() => {
if (props.userDetails.id) {
setFormFields(props.userDetails);
}
}, [props.userDetails])
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.
You need to install the following npm libraries to get supports for Redux configuration.
After installation, you need to create the below files for Action, Reducers, and Store, have a closure look for 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
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.
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.
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
Happy Coding!
Leave a Reply
Your email address will not be published. Required fields are marked *