Skip to content

Commit b3ed3b4

Browse files
committed
Redux: Redux toolkit implemented
1 parent eba2d59 commit b3ed3b4

File tree

12 files changed

+461
-8
lines changed

12 files changed

+461
-8
lines changed

.env

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
PORT=3500
2+
NODE_ENV=development

package.json

+5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
]
3434
},
3535
"dependencies": {
36+
"@reduxjs/toolkit": "^1.5.0",
3637
"@testing-library/jest-dom": "^5.11.9",
3738
"@testing-library/react": "^11.2.3",
3839
"@testing-library/user-event": "^12.6.2",
@@ -43,7 +44,9 @@
4344
"react": "^17.0.1",
4445
"react-dom": "^17.0.1",
4546
"react-dotenv": "^0.1.3",
47+
"react-redux": "^7.2.2",
4648
"react-scripts": "4.0.1",
49+
"redux-logger": "^3.0.6",
4750
"typescript": "^4.1.3",
4851
"web-vitals": "^1.1.0"
4952
},
@@ -53,6 +56,8 @@
5356
"@storybook/addon-essentials": "^6.1.15",
5457
"@storybook/addon-links": "^6.1.15",
5558
"@storybook/react": "^6.1.15",
59+
"@types/react-redux": "^7.1.16",
60+
"@types/redux-logger": "^3.0.8",
5661
"@typescript-eslint/eslint-plugin": "^4.14.1",
5762
"@typescript-eslint/parser": "^4.14.1",
5863
"eslint": "^7.18.0",

public/env.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
window.env = {
22
ALLUSERSPROFILE: "C:\\ProgramData",
3-
ANDROID_HOME: "C:\\Users\\phpch\\AppData\\Local\\Android\\Sdk",
3+
ANDROID_HOME: "%LOCALAPPDATA%\\Android\\Sdk",
44
ANDROID_SDK_ROOT: "C:\\Users\\phpch\\AppData\\Local\\Android\\Sdk",
55
APPDATA: "C:\\Users\\phpch\\AppData\\Roaming",
66
ChocolateyInstall: "C:\\ProgramData\\chocolatey",
77
ChocolateyLastPathUpdate: "132555791491835955",
88
ChocolateyToolsLocation: "C:\\tools",
9-
CHROME_CRASHPAD_PIPE_NAME: "\\\\.\\pipe\\crashpad_2968_WLOWMBROSLPNURMF",
9+
CHROME_CRASHPAD_PIPE_NAME: "\\\\.\\pipe\\crashpad_26736_NLCGGZRTSNEVNFDG",
1010
COLORTERM: "truecolor",
1111
CommonProgramFiles: "C:\\Program Files\\Common Files",
1212
"CommonProgramFiles(x86)": "C:\\Program Files (x86)\\Common Files",
@@ -31,6 +31,7 @@ window.env = {
3131
MOZ_PLUGIN_PATH:
3232
"C:\\PROGRAM FILES (X86)\\FOXIT SOFTWARE\\FOXIT READER\\plugins\\",
3333
NODE: "C:\\Program Files\\nodejs\\node.exe",
34+
NODE_ENV: "development",
3435
npm_config_argv:
3536
'{"remain":[],"cooked":["run","start"],"original":["start"]}',
3637
npm_config_bin_links: "true",
@@ -60,9 +61,12 @@ window.env = {
6061
npm_package_dependencies_react: "^17.0.1",
6162
npm_package_dependencies_react_dom: "^17.0.1",
6263
npm_package_dependencies_react_dotenv: "^0.1.3",
64+
npm_package_dependencies_react_redux: "^7.2.2",
6365
npm_package_dependencies_react_scripts: "4.0.1",
66+
npm_package_dependencies_redux_logger: "^3.0.6",
6467
npm_package_dependencies_typescript: "^4.1.3",
6568
npm_package_dependencies_web_vitals: "^1.1.0",
69+
npm_package_dependencies__reduxjs_toolkit: "^1.5.0",
6670
npm_package_dependencies__testing_library_jest_dom: "^5.11.9",
6771
npm_package_dependencies__testing_library_react: "^11.2.3",
6872
npm_package_dependencies__testing_library_user_event: "^12.6.2",
@@ -88,6 +92,8 @@ window.env = {
8892
npm_package_devDependencies__storybook_react: "^6.1.15",
8993
npm_package_devDependencies__typescript_eslint_eslint_plugin: "^4.14.1",
9094
npm_package_devDependencies__typescript_eslint_parser: "^4.14.1",
95+
npm_package_devDependencies__types_react_redux: "^7.1.16",
96+
npm_package_devDependencies__types_redux_logger: "^3.0.8",
9197
npm_package_eslintConfig_extends_0: "react-app",
9298
npm_package_eslintConfig_extends_1: "react-app/jest",
9399
npm_package_husky_hooks_pre_commit: "lint-staged",
@@ -115,7 +121,7 @@ window.env = {
115121
ORIGINAL_XDG_CURRENT_DESKTOP: "undefined",
116122
OS: "Windows_NT",
117123
Path:
118-
"C:\\Users\\phpch\\AppData\\Local\\Temp\\yarn--1611732138449-0.8781164243421082;G:\\---WorkFiles\\starter\\react-starter-ts\\node_modules\\.bin;C:\\Users\\phpch\\AppData\\Local\\Yarn\\Data\\link\\node_modules\\.bin;C:\\Users\\phpch\\AppData\\Local\\Yarn\\bin;C:\\Program Files\\libexec\\lib\\node_modules\\npm\\bin\\node-gyp-bin;C:\\Program Files\\lib\\node_modules\\npm\\bin\\node-gyp-bin;C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\node-gyp-bin;C:\\Program Files\\PowerShell\\7;C:\\Python39\\Scripts\\;C:\\Python39\\;C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath;C:\\Python38\\Scripts\\;C:\\Python38\\;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files\\Git\\cmd;C:\\Program Files (x86)\\Yarn\\bin\\;C:\\jdk-15\\bin;C:\\Program Files\\Microsoft VS Code\\bin;C:\\Program Files\\Amazon\\AWSCLIV2\\;C:\\Program Files (x86)\\Gpg4win\\..\\GnuPG\\bin;C:\\Users\\phpch\\AppData\\Roaming\\Python\\Python38\\site-packages;C:\\Program Files\\Redis\\;C:\\Users\\phpch\\AppData\\Roaming\\npm;C:\\Program Files\\MongoDB\\Server\\4.4\\bin;C:\\Go\\bin;C:\\composer;G:\\xampp7\\php;C:\\Program Files\\PowerShell\\7\\;C:\\Program Files\\nodejs\\;C:\\Program Files\\Docker\\Docker\\resources\\bin;C:\\ProgramData\\DockerDesktop\\version-bin;C:\\Python39\\Scripts\\;C:\\Python39\\;C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath;C:\\Python38\\Scripts\\;C:\\Python38\\;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files\\Git\\cmd;C:\\Program Files (x86)\\Yarn\\bin\\;C:\\jdk-15\\bin;C:\\Program Files\\Microsoft VS Code\\bin;C:\\Program Files\\Amazon\\AWSCLIV2\\;C:\\Program Files (x86)\\Gpg4win\\..\\GnuPG\\bin;C:\\Users\\phpch\\AppData\\Roaming\\Python\\Python38\\site-packages;C:\\Program Files\\Redis\\;C:\\Users\\phpch\\AppData\\Roaming\\npm;C:\\Program Files\\MongoDB\\Server\\4.4\\bin;C:\\Go\\bin;C:\\composer;G:\\xampp7\\php;C:\\Program Files\\PowerShell\\7\\;C:\\Program Files\\nodejs\\;C:\\Program Files\\Docker\\Docker\\resources\\bin;C:\\ProgramData\\DockerDesktop\\version-bin;C:\\Program Files\\Amazon\\ECSCLI;C:\\Users\\phpch\\AppData\\Roaming\\Python\\Python38\\site-packages;C:\\Program Files\\JetBrains\\WebStorm 2020.2.3\\bin;;C:\\xampp\\php;C:\\Python38\\Scripts;C:\\Program Files\\heroku\\bin;C:\\flutter\\bin;C:\\tools\\dart-sdk\\bin;C:\\Users\\phpch\\AppData\\Roaming\\Pub\\Cache\\bin;C:\\Users\\phpch\\AppData\\Local\\Android\\Sdk\\platform-tools;C:\\Users\\phpch\\go\\bin;G:\\wamp64\\bin\\php\\php7.4.9;C:\\Users\\phpch\\AppData\\Roaming\\Composer\\vendor\\bin;G:\\xampp7\\php;C:\\Users\\phpch\\AppData\\Roaming\\npm",
124+
"C:\\Users\\phpch\\AppData\\Local\\Temp\\yarn--1611897695983-0.792905216640861;G:\\---WorkFiles\\starter\\react-starter-ts\\node_modules\\.bin;C:\\Users\\phpch\\AppData\\Local\\Yarn\\Data\\link\\node_modules\\.bin;C:\\Users\\phpch\\AppData\\Local\\Yarn\\bin;C:\\Program Files\\libexec\\lib\\node_modules\\npm\\bin\\node-gyp-bin;C:\\Program Files\\lib\\node_modules\\npm\\bin\\node-gyp-bin;C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\node-gyp-bin;C:\\Program Files\\PowerShell\\7;C:\\Python39\\Scripts\\;C:\\Python39\\;C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath;C:\\Python38\\Scripts\\;C:\\Python38\\;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files\\Git\\cmd;C:\\Program Files (x86)\\Yarn\\bin\\;C:\\jdk-15\\bin;C:\\Program Files\\Microsoft VS Code\\bin;C:\\Program Files\\Amazon\\AWSCLIV2\\;C:\\Program Files (x86)\\Gpg4win\\..\\GnuPG\\bin;C:\\Users\\phpch\\AppData\\Roaming\\Python\\Python38\\site-packages;C:\\Program Files\\Redis\\;C:\\Windows\\system32\\config\\systemprofile\\AppData\\Roaming\\npm;C:\\Program Files\\MongoDB\\Server\\4.4\\bin;C:\\Go\\bin;C:\\composer;G:\\xampp7\\php;C:\\Program Files\\PowerShell\\7\\;C:\\Program Files\\nodejs\\;C:\\Program Files\\Docker\\Docker\\resources\\bin;C:\\ProgramData\\DockerDesktop\\version-bin;C:\\Python39\\Scripts\\;C:\\Python39\\;C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath;C:\\Python38\\Scripts\\;C:\\Python38\\;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files\\Git\\cmd;C:\\Program Files (x86)\\Yarn\\bin\\;C:\\jdk-15\\bin;C:\\Program Files\\Microsoft VS Code\\bin;C:\\Program Files\\Amazon\\AWSCLIV2\\;C:\\Program Files (x86)\\Gpg4win\\..\\GnuPG\\bin;C:\\Users\\phpch\\AppData\\Roaming\\Python\\Python38\\site-packages;C:\\Program Files\\Redis\\;C:\\Windows\\system32\\config\\systemprofile\\AppData\\Roaming\\npm;C:\\Program Files\\MongoDB\\Server\\4.4\\bin;C:\\Go\\bin;C:\\composer;G:\\xampp7\\php;C:\\Program Files\\PowerShell\\7\\;C:\\Program Files\\nodejs\\;C:\\Program Files\\Docker\\Docker\\resources\\bin;C:\\ProgramData\\DockerDesktop\\version-bin;C:\\Program Files\\Amazon\\ECSCLI;C:\\Users\\phpch\\AppData\\Roaming\\Python\\Python38\\site-packages;C:\\Program Files\\JetBrains\\WebStorm 2020.2.3\\bin;;C:\\xampp\\php;C:\\Python38\\Scripts;C:\\Program Files\\heroku\\bin;C:\\flutter\\bin;C:\\tools\\dart-sdk\\bin;C:\\Users\\phpch\\AppData\\Roaming\\Pub\\Cache\\bin;C:\\Users\\phpch\\AppData\\Local\\Android\\Sdk\\platform-tools;C:\\Users\\phpch\\go\\bin;G:\\wamp64\\bin\\php\\php7.4.9;C:\\Users\\phpch\\AppData\\Roaming\\Composer\\vendor\\bin;G:\\xampp7\\php;C:\\Users\\phpch\\AppData\\Roaming\\npm",
119125
PATHEXT: ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JSE;.WSF;.WSH;.MSC;.PY;.PYW;.CPL",
120126
PhpStorm: "C:\\Program Files\\JetBrains\\PhpStorm 2020.2.1\\bin;",
121127
PORT: "3500",

src/App/App.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
import React, { FC } from "react";
2+
import Count from "./Components/Count";
3+
import User from "./Components/User";
24

35
const App: FC = () => {
46
return (
57
<div className="App">
6-
<h1>React Starter TS</h1>
8+
<h1>React Starter TS!</h1>
9+
<hr />
10+
<Count />
11+
<hr />
12+
<User />
713
</div>
814
);
915
};

src/App/Components/Count.tsx

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import React, {
2+
FC,
3+
useState,
4+
useEffect,
5+
FormEvent,
6+
SyntheticEvent,
7+
ChangeEvent,
8+
} from "react";
9+
10+
import { useSelector, useDispatch } from "react-redux";
11+
import { selectCount, countActions } from "../../store/slices/count.slice";
12+
13+
const Count: FC = () => {
14+
const count = useSelector(selectCount);
15+
16+
const dispatch = useDispatch();
17+
18+
const handleIncrement = (e: SyntheticEvent) => {
19+
e.preventDefault();
20+
dispatch(countActions.increment());
21+
};
22+
23+
const handleIncrementByNumber = (e: SyntheticEvent) => {
24+
e.preventDefault();
25+
dispatch(countActions.incrementByAmount(amount));
26+
};
27+
28+
const handleDecrement = (e: SyntheticEvent) => {
29+
e.preventDefault();
30+
dispatch(countActions.decrement());
31+
};
32+
33+
const [amount, setAmount] = useState(0);
34+
35+
const handleInputChange = (num: number) => {
36+
setAmount(num);
37+
};
38+
39+
return (
40+
<div>
41+
<h1>Count Slice</h1>
42+
<form action="">
43+
<input
44+
type="text"
45+
name="number"
46+
id="number"
47+
onChange={(e) =>
48+
handleInputChange(parseInt(e.target.value))
49+
}
50+
/>
51+
<button onClick={handleIncrement}>Increase</button>
52+
<button onClick={handleDecrement}>Decrement</button>
53+
<button onClick={handleIncrementByNumber}>
54+
Increment by Number
55+
</button>
56+
</form>
57+
<br />
58+
<h3>Count value: {count}</h3>
59+
</div>
60+
);
61+
};
62+
63+
export default Count;

src/App/Components/User.tsx

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React, { FC, useState } from "react";
2+
3+
import { useSelector, useDispatch } from "react-redux";
4+
5+
import {
6+
getUserState,
7+
userActions,
8+
IUserState,
9+
initialUserState,
10+
} from "../../store/slices/user.slice";
11+
12+
const User: FC = () => {
13+
const userObject = useSelector(getUserState);
14+
15+
const dispatch = useDispatch();
16+
17+
const [user, setUser] = useState(initialUserState);
18+
19+
const onUserChange = <P extends keyof IUserState>(
20+
prop: P,
21+
value: IUserState[P]
22+
) => {
23+
setUser({ ...user, [prop]: value });
24+
};
25+
26+
const handleSubmit = () => {
27+
console.log(user);
28+
if (user.username && user.email && user.age)
29+
dispatch(userActions.updateUser(user));
30+
};
31+
32+
return (
33+
<div>
34+
<h1>User Slice</h1>
35+
<input
36+
type="text"
37+
name="username"
38+
id="username"
39+
placeholder="Username"
40+
required
41+
onChange={(e) => onUserChange("username", e.target.value)}
42+
/>
43+
<input
44+
type="text"
45+
name="email"
46+
id="email"
47+
placeholder="Email"
48+
required
49+
onChange={(e) => onUserChange("email", e.target.value)}
50+
/>
51+
<input
52+
type="text"
53+
name="age"
54+
id="age"
55+
placeholder="Age"
56+
required
57+
onChange={(e) => onUserChange("age", parseInt(e.target.value))}
58+
/>
59+
<input type="submit" value="Submit" onClick={handleSubmit} />
60+
<br />
61+
<br />
62+
Username: {userObject.username} | Email: {userObject.email} | Age:{" "}
63+
{userObject.age}
64+
<br />
65+
Loading: {userObject.loadingStatus} | Error: {userObject.error}
66+
</div>
67+
);
68+
};
69+
70+
export default User;

src/index.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@ import App from "./App/App";
66
// Optional measuring performance
77
// import reportWebVitals from "./reportWebVitals";
88

9+
import store from "./store/store";
10+
import { Provider } from "react-redux";
11+
912
ReactDOM.render(
1013
<StrictMode>
11-
<App />
14+
<Provider store={store}>
15+
<App />
16+
</Provider>
1217
</StrictMode>,
1318
document.getElementById("root")
1419
);

src/store/rootReducers.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { combineReducers } from "@reduxjs/toolkit";
2+
import { countReducer, COUNT_SLICE_KEY } from "./slices/count.slice";
3+
import { userReducer, USER_SLICE_KEY } from "./slices/user.slice";
4+
5+
const rootReducer = combineReducers({
6+
[COUNT_SLICE_KEY]: countReducer,
7+
[USER_SLICE_KEY]: userReducer,
8+
});
9+
10+
// Type for whole reducer object
11+
export type RootState = ReturnType<typeof rootReducer>;
12+
13+
export default rootReducer;

src/store/slices/count.slice.ts

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import {
2+
createEntityAdapter,
3+
createSelector,
4+
createSlice,
5+
EntityState,
6+
PayloadAction,
7+
} from "@reduxjs/toolkit";
8+
9+
export const COUNT_SLICE_KEY = "count";
10+
11+
export interface ICountEntity {
12+
id: number;
13+
}
14+
15+
export interface ICountState extends EntityState<ICountEntity> {
16+
loadingStatus: "not loaded" | "loading" | "loaded" | "error";
17+
error: string | null;
18+
count: number;
19+
}
20+
21+
export const countAdapter = createEntityAdapter<ICountEntity>();
22+
23+
export const initialCountState: ICountState = countAdapter.getInitialState({
24+
loadingStatus: "not loaded",
25+
error: null,
26+
count: 0,
27+
});
28+
29+
export const countSlice = createSlice({
30+
name: COUNT_SLICE_KEY,
31+
initialState: initialCountState,
32+
reducers: {
33+
increment: (state) => {
34+
state.count += 1;
35+
state.loadingStatus = "loaded";
36+
},
37+
decrement: (state) => {
38+
state.count -= 1;
39+
},
40+
incrementByAmount: (state, { payload }: PayloadAction<number>) => {
41+
state.count += payload;
42+
state.loadingStatus = "error";
43+
},
44+
add: countAdapter.addOne,
45+
remove: countAdapter.removeOne,
46+
},
47+
});
48+
49+
export const countReducer = countSlice.reducer;
50+
51+
export const countActions = countSlice.actions;
52+
53+
const { selectAll, selectEntities } = countAdapter.getSelectors();
54+
55+
export const getCountState = (state: {
56+
[COUNT_SLICE_KEY]: ICountState;
57+
}): ICountState => {
58+
return state[COUNT_SLICE_KEY];
59+
};
60+
61+
export const selectAllCount = createSelector(getCountState, selectAll);
62+
63+
export const selectCountEntities = createSelector(
64+
getCountState,
65+
selectEntities
66+
);
67+
68+
export const selectCount = (state: {
69+
[COUNT_SLICE_KEY]: ICountState;
70+
}): number => state[COUNT_SLICE_KEY].count;

0 commit comments

Comments
 (0)