redux-2_redux的使用

Tutorial: React基础 Category: React Published: 2026-04-07 13:58:26 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
    
  2. 创建 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;
    
  3. 创建 store => src\store\store.js

    import { configureStore } from "@reduxjs/toolkit";
    
    // 导入 reducer
    import counterReducer from "./features/counterSlice";
    
    export default configureStore({
      reducer: {
        counter: counterReducer,
      },
    });
    
  4. 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>
    );
    
  5. 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;
    
  6. 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;
    
  2. store.js 添加

    import helloReducer from "./features/helloSlice";
    ...
    reducer: {
         counter: counterReducer,
         hello: helloReducer,
     },
    ...
    
  3. App.jsx 添加组件 Hello

    import Hello from "./components/Hello";
    return (
      <div className="App">
        <p>app</p>
        <Counter />
        <Hello />
      </div>
    );
    
  4. 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>
      );
    }
    
Prev: redux-1_创建项目 Next: None