React 有旧版本的 createStore 和新版本的 configureStore,旧版本的已经不推荐使用,现对 configureStore 进行简单的使用说明。适用于类组件和函数组件。
npm install @reduxjs/toolkit react-redux
安装 @reduxjs/toolkit 和 react-redux
第一步:在src文件夹下创建目录 store 在store中分别创建 index.js 和 counter_slice.js 两个文件。
在 index.js 中
import { configureStore } from '@reduxjs/toolkit'
// counter_slice 相当于配置文件 名字随便取
import counterSlice from "./counter_slice.js"
// 将配置文件引入redux中。同理,若有其他文件也是一样的配置
const store = configureStore({
reducer: {
counter: counterSlice,
}
})
export default store
在 counter_slice.js 中
import { createSlice } from '@reduxjs/toolkit'
// 创建数据和方法
const counterSlice = createSlice({
// 名称 对应index.js 文件中的reducer对象中的key
name: "counter",
// 初始化的数据
initialState: {
number: 0
},
// 方法
reducers: {
add: (state, actions) => {
// actions 中有 type 和 payload 两个值
// console.log(state, actions)
state.number = actions.payload
},
sub: (state, actions) => {
state.number = actions.payload
}
}
})
export const { add, sub } = counterSlice.actions // 暴露方法
export default counterSlice.reducer // 导出reducer传给index.js
在 src/index.js 中,通过 < Provider > 将 组件包裹起来,并将store作为prop传入。
...
import React from 'react';
import ReactDOM from 'react-dom/client';
import TodoList from './TodoList';
import 'antd/dist/antd.css'; // 全局样式
import { Provider } from 'react-redux';
import store from './store'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<TodoList props="props-param"/>
</Provider>
);
在组件todolist.js 中
import { add, sub } from './store/counter_slice';
import { useDispatch, useSelector } from 'react-redux';
// 从 redux 取出 number
const number = useSelector((state) => {
// console.log(state)
return state.counter.number
// counter 对应/src/store/index.js 文件中的counter
})
const dispatch = useDispatch()
// 通过 dispatch 将更新值
const handleAdd = () => {
dispatch(add(inputValue))
}
import React, { Fragment, useState, useEffect } from "react"
import { add, sub } from './store/counter_slice';
import { useDispatch, useSelector } from 'react-redux';
// 引入样式文件
import "./style.css"
// 函数组件
function TodoList(props) {
const [inputValue, setInputValue] = useState("")
const dispatch = useDispatch()
const handleAdd = () => {
dispatch(add(inputValue))
}
const handleInput = (e) => {
const newValue = e.target.value
setInputValue(newValue)
}
// 从 redux 取出 number
const number = useSelector((state) => {
// console.log(state)
return state.counter.number
})
return (
<div>
<div>
<input value={inputValue} placeholder="input a value" style={{width: "300px" }} onChange={handleInput} />
<button type="primary" onClick={handleAdd}>更新</button>
</div>
<div>获取store中的值: {number}</div>
</div>
)
}
// 导出组件
export default TodoList;
在操作数据的时候难免会遇到异步操作,React中用到的时候”中间件“的概念(thunk),理解起来较为复杂,具体的内容网上有专业的知识,此处简单讲解其中的一种使用方法。
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import axios from "axios"
// 异步函数
export const testFn = createAsyncThunk("counterSlice/testFn", async (param, api) => {
// console.log(param, api)
const { data } = await axios.get("http://bill.cc:3000/api/todolist1")
return data
})
const counterSlice = createSlice({
name: "counter",
initialState: {
number: 0
},
reducers: {
add: (state, actions) => {
// console.log(state, actions)
state.number = actions.payload
},
sub: (state, actions) => {
state.number = actions.payload
}
},
// 异步处理
extraReducers: {
// 异步promise发生success
[testFn.fulfilled]: (state, actions) => {
console.log(actions)
state.number = actions.payload
},
// 异步promise发生rejected
[testFn.rejected]: (state, actions) => {
console.log(actions)
state.number = "axios 请求发生错误"
}
}
})
export const { add, sub } = counterSlice.actions // 暴露方法(同步方法)
export default counterSlice.reducer
从 @reduxjs/toolkit 中导出 createAsyncThunk,用这个函数创建异步函数。
在 createSlice 中的 extraReducers 接收异步函数 testFn 请求的结果并更新到store中。
至此,store简单的使用介绍完毕,弄懂一遍第二遍就快很多。