redux-2_redux的使用
Redux 的使用
一、创建 reducer => counter
-
项目文件
$ 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 -
创建 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; -
创建 store => src\store\store.js
import { configureStore } from "@reduxjs/toolkit"; // 导入 reducer import counterReducer from "./features/counterSlice"; export default configureStore({ reducer: { counter: counterReducer, }, }); -
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> ); -
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; -
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
-
创建 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; -
store.js 添加
import helloReducer from "./features/helloSlice"; ... reducer: { counter: counterReducer, hello: helloReducer, }, ... -
App.jsx 添加组件 Hello
import Hello from "./components/Hello"; return ( <div className="App"> <p>app</p> <Counter /> <Hello /> </div> ); -
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> ); }