Эх сурвалжийг харах

Redux: 异步处理&计数器案例

大侠 2 жил өмнө
parent
commit
0a5d112a92

+ 55 - 1
15_React/day-6/code/learn-redux/src/pages/Counter.jsx

@@ -1,7 +1,61 @@
-export default function counter() {
+import styles from './counter.module.css';
+import { addOne, reduceOne, addBy, asyncAddBy } from '../store/slices/counter';
+import { useSelector, useDispatch } from 'react-redux';
+import { useState } from 'react';
+
+// console.log(styles);
+
+function Counter() {
+  const c = useSelector(({ counter }) => counter.c);
+  const dispatch = useDispatch();
+  let [nc, setNC] = useState('');
+
   return (
     <div>
       <h3>计数器</h3>
+      <div className={styles.row}>
+        <button
+          className={styles.button}
+          onClick={() => {
+            dispatch(reduceOne());
+          }}
+        >
+          -
+        </button>
+        <span className={styles.value}>{c}</span>
+        <button
+          className={styles.button}
+          onClick={() => {
+            dispatch(addOne());
+          }}
+        >
+          +
+        </button>
+      </div>
+      <div className={styles.row}>
+        <input
+          className={styles.textbox}
+          value={nc}
+          onChange={(e) => setNC(e.target.value)}
+        />
+        <button
+          className={styles.button}
+          onClick={() => {
+            dispatch(addBy(Number(nc) || 0));
+          }}
+        >
+          Add Amount
+        </button>
+        <button
+          className={styles.asyncButton}
+          onClick={() => {
+            dispatch(asyncAddBy(Number(nc) || 0));
+          }}
+        >
+          Add Async
+        </button>
+      </div>
     </div>
   );
 }
+export default Counter;

+ 8 - 1
15_React/day-6/code/learn-redux/src/pages/Home.jsx

@@ -1,6 +1,6 @@
 import { useState } from 'react';
 import { useSelector, useDispatch } from 'react-redux';
-import { setName, setAge } from '../store/slices/user-silce';
+import { setName, setAge, asyncSetAge } from '../store/slices/user-silce';
 
 export default function Home() {
   const dispatch = useDispatch();
@@ -53,6 +53,13 @@ export default function Home() {
           >
             修改age
           </button>
+          <button
+            onClick={() => {
+              dispatch(asyncSetAge(age));
+            }}
+          >
+            1s后修改age
+          </button>
         </p>
       </div>
     </div>

+ 76 - 0
15_React/day-6/code/learn-redux/src/pages/counter.module.css

@@ -0,0 +1,76 @@
+.row {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.row:not(:last-child) {
+  margin-bottom: 16px;
+}
+
+.value {
+  font-size: 78px;
+  padding-left: 16px;
+  padding-right: 16px;
+  margin-top: 2px;
+  font-family: 'Courier New', Courier, monospace;
+}
+
+.button {
+  appearance: none;
+  border: none;
+  background: none;
+  font-size: 32px;
+  padding-left: 12px;
+  padding-right: 12px;
+  outline: none;
+  border: 2px solid transparent;
+  color: rgb(112, 76, 182);
+  padding-bottom: 4px;
+  cursor: pointer;
+  background-color: rgba(112, 76, 182, 0.1);
+  border-radius: 2px;
+  transition: all 0.15s;
+}
+
+.textbox {
+  font-size: 32px;
+  padding: 2px;
+  width: 64px;
+  text-align: center;
+  margin-right: 8px;
+}
+
+.button:hover,
+.button:focus {
+  border: 2px solid rgba(112, 76, 182, 0.4);
+}
+
+.button:active {
+  background-color: rgba(112, 76, 182, 0.2);
+}
+
+.asyncButton {
+  composes: button;
+  position: relative;
+  margin-left: 8px;
+}
+
+.asyncButton:after {
+  content: '';
+  background-color: rgba(112, 76, 182, 0.15);
+  display: block;
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  left: 0;
+  top: 0;
+  opacity: 0;
+  transition: width 1s linear, opacity 0.5s ease 1s;
+}
+
+.asyncButton:active:after {
+  width: 0%;
+  opacity: 1;
+  transition: 0s;
+}

+ 2 - 0
15_React/day-6/code/learn-redux/src/store/index.js

@@ -1,5 +1,6 @@
 import { configureStore } from '@reduxjs/toolkit';
 import userReducer from './slices/user-silce';
+import counterReducer from './slices/counter';
 
 // const reducer = (state, action) => {
 //   return {
@@ -12,6 +13,7 @@ import userReducer from './slices/user-silce';
 const store = configureStore({
   reducer: {
     user: userReducer,
+    counter: counterReducer,
   },
   // reducer,
 });

+ 30 - 0
15_React/day-6/code/learn-redux/src/store/slices/counter.js

@@ -0,0 +1,30 @@
+import { createSlice } from '@reduxjs/toolkit';
+
+const initialState = {
+  c: 0,
+};
+
+export const counterSlice = createSlice({
+  name: 'counter',
+  initialState,
+  reducers: {
+    addOne(state) {
+      state.c++;
+    },
+    reduceOne(state) {
+      state.c--;
+    },
+    addBy(state, { payload }) {
+      state.c += payload;
+    },
+  },
+});
+
+export default counterSlice.reducer;
+export const { addOne, reduceOne, addBy } = counterSlice.actions;
+
+export const asyncAddBy = (val) => (dispatch) => {
+  setTimeout(() => {
+    dispatch(addBy(val)); // {type: '', payload:val}
+  }, 1000);
+};

+ 26 - 0
15_React/day-6/code/learn-redux/src/store/slices/user-silce.js

@@ -28,3 +28,29 @@ export default userSlice.reducer;
 
 // Action Creator
 export const { setName, setAge } = userSlice.actions;
+
+// 异步处理,需要定义thunk函数
+// export function asyncSetAge(age) {
+//   return (dispatch, getState) => {
+//     setTimeout(() => {
+//       dispatch(setAge(Number(age) || 0));
+//     }, 1000);
+//   };
+// }
+
+// 上面代码优化
+export const asyncSetAge = (age) => (dispatch, getState) => {
+  setTimeout(() => {
+    dispatch(setAge(Number(age) || 0));
+  }, 1000);
+};
+
+// export const asyncSetAge = (dispatch, getState) => {
+//   // console.log(dispatch);
+//   // console.log(getState);
+//   // let state = getState();
+//   // console.log(state);
+//   setTimeout(() => {
+//     dispatch(setAge(Number(age) || 0));
+//   }, 1000);
+// };