Redux在React中的简单使用

97 阅读4分钟

Redux是什么

和Vue中的Vuex和Pinia一样,Redux是一个状态管理库,不过我觉得Redux相比于Vuex更为简洁,因为Redux没有Vuex中的Mutation,在Redux中,用store来存储数据,用action来修改数据,简单明了。

image.png 当然,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;

image.png

利用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

image.png 这里我们把定义好的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>,
);

image.png

案例展示

通过上面的步骤,我们创建了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

image.png

image.png

image.png 以上就是最基本的Redux使用,当然,如果随着模块越来越多,我们不可能将状态都放在一个文件中,因此需要进行模块化的处理

Redux的多模块化使用

将store拆分模块

比如我想管理两个模块的状态,此时在store文件下新建两个文件夹,两个文件夹分别管理自己的状态,然后在main.ts中把状态都导入进来,再和项目连接起来即可 image.png

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

页面效果如下:

image.png

image.png

总结

  1. 写一个store的普通函数对象
  2. 利用createStore把这个函数对象变成真正的仓库(如果是模块化状态管理,该步之前要用combineReducers进行模块化)
  3. 利用Provider把这个仓库和项目(APP.tsx)连接起来即可