ThatManK Mobile Article
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>
);
}