Redux是一个强大的JavaScript状态管理库,它被广泛应用于React和其他前端框架。然而,Redux的繁琐和冗长的代码编写方式一直以来都是开发者们所诟病的。为了解决这个问题,Redux官方推出了Redux Toolkit,它是一个开箱即用的工具集,旨在简化Redux的使用并提供更好的开发体验。本篇博客将带您深入了解Redux Toolkit;
下载使用
npm install @reduxjs/toolkit react-redux
redux单独的使用
为了方便大家去理解,我就把redux创建全写一个文件了;
import { createStore } from "redux";
const ADD_NUM = 'add'
export const add = num => ({
type: ADD_NUM,
payload: { num }
})
const initState = {
count: 0,
}
export const countReducer = (state = initState, action) => {
switch (action.type) {
case ADD_NUM:
return {
count: state.count + action.payload.num
}
default:
return state
}
}
const store = createStore(countReducer)
export default store
这样,一个完整的状态管理仓库就创建好了,接下来就是使用react的Provider组件进行注册了;
import App from './App.jsx';
import { Provider } from 'react-redux'
import store from './store'
const Application = (
<Provider store={store}>
<App />
</Provider>
)
结下来就是咋们的使用环节了 方式1:使用store中的getState()获取值
// 方式1
function App () {
// counter 不是响应式的
const counter = store.getState().counter
return <div>值:{{counter}}</div>
}
方法2:使用react-redux的useSelector
import { useSelector } from 'react-redux';
function App() {
// counter 是响应式的
const counter = useSelector(state => state.counter);
return <div>值:{counter}</div>;
}
方法3:使用react-redux的高阶组件connect
import { connect } from 'react-redux';
function App({ counter }) {
// counter 是响应式的
return <div>值:{counter}</div>;
}
export default connect(state => ({
counter: state.counter,
}))(App);
dispatch派发action
dispatch 是 Redux 中用于派发(触发) action 的函数。在 Redux 中,通过派发 action 来改变应用的状态。dispatch 函数接受一个 action 对象作为参数,然后将该 action 发送到 Redux Store 中,触发相应的 reducer 处理状态更新
import { connect,useDispatch } from 'react-redux';
import { add } from '{上面创建redux仓库的文件地址}';
function App({ counter }) {
const dispatch = useDispatch();
const add = () => {
dispatch(add(1))
}
return <div>
<span>值:{counter}</span>
<button onClick={add}>加1</button>
</div>;
}
export default connect(state => ({
counter: state.counter,
}))(App);
在上面这段代码中,我们从useDispatch获取到了dispatch,通过dispatch派发action去修改状态,这样,我们就实现了派发;
上面代码运行的效果:点击【加1】按钮,span标签里面显示的counter就会加一;
异步操作
dispatch函数默认是同步的,一般情况下,是不建议在异步中去使用dispatch,否由于异步操作的执行时间不确定,如果在异步操作完成之前多次调用 dispatch,可能会导致多个相同或不同的 action 同时在处理,这可能会导致状态的混乱和不可预测的结果。
为了去支持异步调用dispatch,我们可以使用异步中间件redux-thunk,结下来我们使用redux-thunk对前面的状态管理仓库进行改造
import { createStore, applyMiddleware } from "redux";
import thunkMiddleware from 'redux-thunk';
const ADD_NUM = 'add'
export const add = num => ({
type: ADD_NUM,
payload: { num }
})
export const asyncDouble = (num) => {
return async (dispatch, getState) => {
const state = getState();
await new Promise((resolve, reject) => {
setTimeout(() => {
dispatch(add(state.count + num));
resolve();
}, 1000);
});
};
};
const initState = {
count: 0,
}
export const countReducer = (state = initState, action) => {
switch (action.type) {
case ADD_NUM:
return {
count: state.count + action.payload.num
}
default:
return state
}
}
const store = createStore(countReducer, applyMiddleware(thunkMiddleware))
export default store
在上面我们加入的redux-thunk中间件,然后定义了asyncDouble的异步方法,接下来使用这个异步函数
import { connect,useDispatch } from 'react-redux';
import { add } from '{上面创建redux仓库的文件地址}';
function App({ counter }) {
const dispatch = useDispatch();
const add = () => {
dispatch(asyncDouble(1))
}
return <div>
<span>值:{counter}</span>
<button onClick={add}>加1</button>
</div>;
}
export default connect(state => ({
counter: state.counter,
}))(App);
这样,我们就完成了异步的调用;但是为什么这样调用就会有效果了呢?
因为redux-thunk中间件会检查 asyncDouble 返回的值。如果返回的是一个函数而不是一个普通的 action 对象,redux-thunk 会将该函数作为参数调用,并传递 dispatch 和 getState 两个函数。这样,我们就可以在返回的函数中执行异步操作;
redux的模块化
import { createStore, combineReducers } from 'redux';
import module1Reducer from './module1/reducer';
import module2Reducer from './module2/reducer';
const rootReducer = combineReducers({
module1: module1Reducer,
module2: module2Reducer,
});
const store = createStore(rootReducer);
export default store;
使用
import { connect } from 'react-redux';
function App({ counter }) {
return <div>值:{counter}</div>;
}
export default connect(state => ({
counter: state.module1.counter,
}))(App);
redux配合toolkit的使用
基于toolkit创建一个状态管理仓库
// /store/counter.js
import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0
},
reducers: {
add: state => {
state.value += 1
},
reducer: state => {
state.value -= 1
},
}
})
// 反回派生事件
export const { add, reducer } = counterSlice.actions
export default counterSlice.reducer
createSlice: createSlice 需要一个字符串名称来标识切片[模块]、一个初始 state 以及一个或多个定义了该如何更新 state 的 reducer 函数。切片创建后 ,我们可以导出切片中生成的Redux派发函数 add和reducer。
// /store/index.js
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'
export default configureStore({
reducer: {
counter: counterReducer
}
})
注册store
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import store from './store'
import { Provider } from 'react-redux'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
状态的使用派生事件的使用基本和上面的案例是一样的; 在toolkit中默认使用redux-thunk作为默认的异步处理中间件;所以在toolkit中的异步处理也基本上和上面的案例是一样的
createAsyncThunk函数
export const fetchPosts = createAsyncThunk('counter/add', async () => {
const response = await client.get('/api/add')
return response.data
})
createAsyncThunk 接收 2 个参数:
第一个将用作生成的 action 类型的前缀的字符串【一般情况下为:模块名/该模块中reducers的键名】 第二个是一个回调函数,它应该返回一个包含一些数据的 Promise,或者一个被拒绝的带有错误的 Promise
大家都看到这了,说明你已经理解怎么去使用redux以及toolkit了,创作不易,求求给个赞吧!🥺🥺🥺