ThatManK Mobile Article

redux-2_redux的使用

Category: React Tutorial: React基础 Published: 2026-04-07 13:58 Views: 20 Likes: 0 Comments: 0

Redux 的使用

一、创建 reducer => counter
  1. 项目文件
   $ ls -R src/
    src/:
    App.jsx  components/  index.js  store/

    src/components:
    Counter/  Hello/

    src/components/Counter:
    index.jsx

    src/components/Hello:
    index.jsx

    src/store:
    features/  store.js

    src/store/features:
    counterSlice.js  helloSlice.js
  1. 创建 createSlice => src\store\features\counterSlice.js
   import { createSlice } from "@reduxjs/toolkit";

   // 导出slice
   export const counterSlice = createSlice({
     name: "counter",

     // state数据
     initialState: {
       value: 0,
       title: "counter demo",
     },

     // 三个方法
     reducers: {
       increment: (state, action) => {
         state.value += 1;
       },

       decrement: (state, action) => {
         state.value -= 1;
       },

       incrementByAmount: (state, action) => {
         state.value += action.payload;
       },
     },
   });

   // 都有导出 actions 里面的方法
   export const { increment, decrement, incrementByAmount } =
     counterSlice.actions;

   // 一个异步方法
   export const incrementAsyncOuter = (amount) => (dispatch) => {
     setTimeout(() => {
       dispatch(incrementByAmount(amount));
     }, 1000);
   };

   // 默认导出 reducer
   export default counterSlice.reducer;
  1. 创建 store => src\store\store.js
   import { configureStore } from "@reduxjs/toolkit";

   // 导入 reducer
   import counterReducer from "./features/counterSlice";

   export default configureStore({
     reducer: {
       counter: counterReducer,
     },
   });
  1. index.js 使用 store
   import React from "react";
   import ReactDOM from "react-dom/client";
   import App from "./App";

   import { Provider } from "react-redux";
   import store from "./store/store";

   const root = ReactDOM.createRoot(document.getElementById("root"));
   root.render(
     <Provider store={store}>
       <App />
     </Provider>
   );
  1. App.js 引入组件
   import "antd/dist/reset.css";
   import Counter from "./components/Counter";

   function App() {
     return (
       <div className="App">
         <p>app</p>
         <Counter />
       </div>
     );
   }

   export default App;
  1. Counter.jsx 中使用 redux 中 counter 的数据和方法
   import React from "react";
   import { useSelector, useDispatch } from "react-redux";
   import {
     decrement,
     increment,
     incrementAsyncOuter,
   } from "./store/features/counterSlice";

   export default function Counter() {
     // 调用方法需要
     const dispatch = useDispatch();

     // 取值
     const count = useSelector((state) => state.counter.value);
     // const title = useSelector(({ counter: { title: name } }) => name);
     const title = useSelector(({ counter: { title } }) => title);

     return (
       <div style={{ border: "1px solid red" }}>
         <div>
           <p>{title}</p>
           <p>{count}</p>
           <button onClick={() => dispatch(increment())}>增加</button>
           <button onClick={() => dispatch(decrement())}>减少</button>
           <button onClick={() => dispatch(incrementAsyncOuter(20))}>
             异步增加(out)
           </button>
         </div>
       </div>
     );
   }
二、创建 reducer => hello
  1. 创建 createSlice => src\store\features\helloSlice.js
   import {
     createSlice,
     createAction,
     createAsyncThunk,
   } from "@reduxjs/toolkit";

   // 演示 createAsyncThunk
   // createAsyncThunk  pending(进行中) => fulfilled(成功) <=> rejected(失败)
   const apiUrl =
     "https://mesh.if.iqiyi.com/portal/videolib/pcw/data?version=1.0&ret_num=30&page_id=1&device_id=b1c4f48b193f88fb52c27232e2b50ea2&passport_id=&recent_selected_tag=%E7%BB%BC%E5%90%88%3B%E6%9B%B4%E6%97%A9%3B%E6%9C%80%E7%83%AD&recent_search_query=&ip=202.108.14.240&channel_id=1&tagName=&mode=11&market_release_date_level=1950-1979";
   // 获取数据
   const getDateApi = () => fetch(apiUrl).then((res) => res.json());
   // 异步方法 注意写法
   export const loadData = createAsyncThunk(
     "hello/loadData",
     async () => await getDateApi()
   );

   export const helloSlice = createSlice({
     name: "hello",

     // state 初始值
     initialState: {
       title: "hello demo",
       msg: "no data",
       nameList: [
         {
           id: "001",
           name: "Tom",
         },
       ],
     },

     // 内部reducer
     reducers: {
       addName: (state, { payload }) => {
         state.nameList = [...state.nameList, payload];
       },
     },

     // 额外reducer
     extraReducers: {
       [loadData.fulfilled](state, { payload }) {
         console.log("ok: ", payload);
         state.msg = JSON.stringify(payload);
       },
       [loadData.pending](state, { payload }) {
         console.log("pending: ", payload);
       },
       [loadData.rejected](state, { payload }) {
         console.log("rejected: ", payload);
       },
     },
   });

   export const { addName } = helloSlice.actions;

   export default helloSlice.reducer;
  1. store.js 添加
   import helloReducer from "./features/helloSlice";
   ...
   reducer: {
        counter: counterReducer,
        hello: helloReducer,
    },
   ...
  1. App.jsx 添加组件 Hello
   import Hello from "./components/Hello";
   return (
     <div className="App">
       <p>app</p>
       <Counter />
       <Hello />
     </div>
   );
  1. Hello 组件调用相关方法和数据
    import React from "react";
    import { useSelector, useDispatch } from "react-redux";
    import { addName, loadData } from "./store/features/helloSlice";
    import { Button, Form, Input } from "antd";

    export default function Hello() {
      const dispatch = useDispatch();
      const title = useSelector(({ hello: { title } }) => title);
      const msg = useSelector(({ hello: { msg } }) => msg);
      const nameList = useSelector(({ hello: { nameList } }) => nameList);

      const onFinish = (obj) => {
        // 添加数据
        dispatch(addName(obj));
      };

      return (
        <div style={{ border: "1px solid blue", marginTop: 20 }}>
          {/* 默认 */}
          <div>
            <p>{title}</p>
            <Form onFinish={onFinish}>
              <Form.Item label="ID" name="id">
                <Input />
              </Form.Item>

              <Form.Item label="Name" name="name">
                <Input />
              </Form.Item>

              <Form.Item>
                <Button type="primary" htmlType="submit">
                  新增
                </Button>
              </Form.Item>
            </Form>
          </div>
          <div>
            {/* 渲染数据 */}
            <ul>
              {nameList.map((item) => (
                <li key={item.id}>{item.id + ":" + item.name}</li>
              ))}
            </ul>
          </div>

          {/* 异步 createAsyncThunk */}
          <div>
            <button onClick={() => dispatch(loadData())}>获取数据</button>
            <div>{msg}</div>
          </div>
        </div>
      );
    }