Redux是什么
和Vue中的Vuex和Pinia一样,Redux是一个状态管理库,不过我觉得Redux相比于Vuex更为简洁,因为Redux没有Vuex中的Mutation,在Redux中,用store来存储数据,用action来修改数据,简单明了。
当然,Redux并不只是用于React,也可以用于其他框架,只是和React使用比较紧密。
Redux的简单使用
安装依赖
首先在React中安装依赖
npm install --save redux
npm install --save react-redux
npm install --save-dev redux-devtools
在src路径下新建store文件夹,在该文件夹下新建两个文件,分别是index.ts和reducer.ts
编写store普通函数对象
在reducer.ts文件中 1)首先写一个函数,形参是state,action,函数体里是action的方法
- 在形参state中,储存了store最原始的数据供其他组件使用
- 在形参action中,提供了action函数来改变数据,当然最后一定要把最新的数据return出去,这样store中的数据就发生了改变
const defaultState = {
num: 20,
};
const reducer = (
state = defaultState,
action: { type: string; val: number }
) => {
const newState = JSON.parse(JSON.stringify(state));
switch (action.type) {
case "add1":
newState.num++;
break;
case "add2":
newState.num += action.val;
break;
default:
break;
}
return newState;
};
export default reducer;
利用createStore把对象变成真正的仓库
在index.ts文件中
2)我们在上述文件中已经定义好了一个reducer并默认导出,在index.ts文件下我们引入这个store,利用createStore方法把第一步定义的函数reducer拿过来,注册到createStore中,createStore(reducer)
import { legacy_createStore} from "redux";
import reducer from "./reducer";
// window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
// 让浏览器redux-dev-tools能正常使用
const store = legacy_createStore(reducer,window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__());
export default store
这里我们把定义好的reducer对象放入了createStore中,这样一个完整的仓库就注册好了,接下来我们要和项目联系起来
把仓库和项目连接起来
在main.ts文件中
import { Provider } from 'react-redux'
import store from "@/store/index";
ReactDOM.createRoot(document.getElementById("root")!).render(
<Provider store={store}>
<App />
</Provider>,
);
案例展示
通过上面的步骤,我们创建了store并和项目进行了连接,接下来我们使用他:
在组件A中引入useSelector用来获取store中的值,useDispatch用来派发action修改store中的值
import {useSelector,useDispatch} from "react-redux"
import { Button } from 'antd';
import {useSelector,useDispatch} from "react-redux"
function One (){
const dispatch = useDispatch();
const {num}=useSelector((state:RootState)=>({
num:state.num
}))
const add1=()=>{
dispatch({type:'add2',val:20})
}
const add2=()=>{
dispatch({type:'add1'})
}
return <>
<h1>num的初始值(从store中拿取)是:{num}</h1>
<Button type="primary" onClick={add1}>add1修改store中的值</Button>
<br/>
<br/>
<Button type="primary" onClick={add2}>add2修改store中的值</Button>
</>
}
export default One
以上就是最基本的Redux使用,当然,如果随着模块越来越多,我们不可能将状态都放在一个文件中,因此需要进行模块化的处理
Redux的多模块化使用
将store拆分模块
比如我想管理两个模块的状态,此时在store文件下新建两个文件夹,两个文件夹分别管理自己的状态,然后在main.ts中把状态都导入进来,再和项目连接起来即可
numState文件夹
index.ts
//这里只是把数据和方法抽离出来,调整起来会更为方便
export default {
state: {
num: 20,
},
actions: {
add1(newState, action) {
newState.num++;
},
add2(newState, action) {
newState.num += action.val;
},
},
add1: "add1",
add2: "add2",
};
reducer.ts
//根据上面文件,更有条理性的撰写store,这个写完,就代表这个store的普通函数对象写好了
import handleNum from "./index";
const reducer = (
state = { ...handleNum.state },
action: { type: string; val: number }
) => {
const newState = JSON.parse(JSON.stringify(state));
switch (action.type) {
case handleNum.add1:
handleNum.actions[handleNum.add1](newState, action);
break;
case handleNum.add2:
handleNum.actions[handleNum.add2](newState, action);
break;
default:
break;
}
return newState;
};
export default reducer;
这样就完成了numState这个模块的store,同理,完成第二个store
weatherState文件夹
index.ts
export default {
state: {
wind: "微风",
},
actions: {
changeWind(newState, action) {
newState.wind='周杰伦的龙卷风'
},
},
changeWind: "changeWind",
};
reducer.ts
import handleWeather from "./index";
const reducer = (
state = { ...handleWeather.state },
action: { type: string; val: number }
) => {
const newState = JSON.parse(JSON.stringify(state));
switch (action.type) {
case handleWeather.changeWind:
handleWeather.actions[handleWeather.changeWind](newState, action);
break;
default:
break;
}
return newState;
};
export default reducer;
等这两个store的普通函数对象写好了之后,我们在main.ts中,在createStore之前,要利用combineReducers来把store进行模块化
main.ts文件夹
// 2)利用createStore方法把第一步定义的函数reducer拿过来,注册到createStore中,createStore(reducer)
import { legacy_createStore,combineReducers} from "redux";
import handleNum from "./numState/reducer";
import handleWeather from "./weatherState/reducer";
// combineReducers是把redux进行模块化
const reducers=combineReducers({
handleNum,
handleWeather
})
const store = legacy_createStore(reducers,window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__());
export default store
这样当在某组件访问某模块下的state时,就需要这样写
B组件
import { Button } from "antd";
import {useSelector,useDispatch} from "react-redux"
function Two(){
const dispatch = useDispatch();
const {wind}=useSelector((state:RootState)=>({
wind:state.handleWeather.wind
}))
console.log(useSelector((state:RootState)=>({
wind:state.handleWeather.wind
})));
const changeWind=()=>{
dispatch({type:'changeWind'})
}
return (
<>
<h1>weatherStore中的值{wind}</h1>
<Button onClick={changeWind}>改变天气</Button>
</>
)
}
export default Two
页面效果如下:
总结
- 写一个store的普通函数对象
- 利用createStore把这个函数对象变成真正的仓库(如果是模块化状态管理,该步之前要用combineReducers进行模块化)
- 利用Provider把这个仓库和项目(APP.tsx)连接起来即可