像Vuex一样使用redux

简介: 【8月更文挑战第16天】像Vuex一样使用redux

redux基础知识

学习文档

  1. 英文文档: https://redux.js.org/
  2. 中文文档: http://www.redux.org.cn/
  3. Github: https://github.com/reactjs/redux
    redux是什么
  4. redux是一个专门用于做状态管理的JS库(不是react插件库)。
  5. 它可以用在react, angular, vue等项目中, 但基本与react配合使用。
  6. 作用: 集中式管理react应用中多个组件共享的状态。
    什么情况下需要使用redux
  7. 某个组件的状态,需要让其他组件可以随时拿到(共享)。
  8. 一个组件需要改变另一个组件的状态(通信)。
  9. 总体原则:能不用就不用, 如果不用比较吃力才考虑使用。

redux的使用

依赖安装

npm i redux react-redux --save

react-redux帮我们在react项目中做了一些关于redux的封装,使我们可以更好的在react项目中使用redux。

引入

我们一般在store文件下的index.ts文件进行store编写

import {
   
    legacy_createStore } from 'redux'
// 一些初始数据
const defaultState = {
   
   
  customerId: null
}
// reducer 是一个函数,它接受先前的状态和当前的 action 作为参数,并返回新的状态。
let reducer = (state=defaultState) => {
   
   
  // 根据旧的state和action, 产生新的state的纯函数。
  return state
}
// 创建一个store
const store = legacy_createStore(reducer)
// 导出一个store
export default store

注:为了便于学习,我们使用了legacy_createStore的早期写法,我们也可以使用createStore及configureStore。

目录优化

我们可以调整项目结构,使我们的代码层级更加清晰
src\store\index.ts

import {
   
    legacy_createStore } from 'redux''
import reducer from './reducer'
// Create a data warehouse
const store = legacy_createStore(reducer)
export default store

src\store\reducer.ts

const defaultState = {
   
   
  customerId: null
}

let reducer = (state = defaultState) => {
   
   
  return state
}
export default reducer

使用useSelector读取state值

React Redux 库提供的 useSelector 钩子来简化获取 Redux 状态的过程。useSelector 允许你选择性地从 Redux 状态树中选择和返回所需的状态值。

import {
   
    useSelector } from 'react-redux';

function CounterDisplay() {
   
   
  // useSelector 接收一个回调函数,该回调函数可以访问 Redux 的状态树并返回所需的状态值。
  // state就是全局状态
  const {
   
    customerId } = useSelector((state) => ({
   
   
    customerId: state.customerId
  }))
  return (
    <div>
    <p>{
   
   customerId}</p>
    </div>
  );
}

安装浏览器工具

我们可以给浏览器安装redux的调试工具Redux DevTools。它可以帮助我们更轻松地调试 Redux 应用程序
image.png
使用此工具,我们需要给项目安装相应的依赖

npm install --save-dev redux-devtools-extension

在创建 store 时,将 Redux DevTools 的中间件添加到 applyMiddleware 函数中:

// src\store\index.ts
import {
   
    legacy_createStore, applyMiddleware } from 'redux'
import {
   
    composeWithDevTools } from 'redux-devtools-extension'
import reducer from './reducer'

const store = legacy_createStore(reducer, composeWithDevTools(applyMiddleware()))

export default store

现在,我们就可以在控制台看到我们安装插件后的效果了
image.png

使用useDispatch修改state的状态值

Redux 中的状态是不可直接修改的,你需要通过触发一个 action,然后在 Reducer 中根据这个 action 的类型来修改状态。

import {
   
    useDispatch } from 'react-redux'

dispatch({
   
    type: 'changeCustomerId', value: value })

src\store\reducer.ts

const defaultState = {
   
   
  customerId: null
}

let reducer = (state = defaultState, action: {
   
    type: string; value: any }) => {
   
   
  let newState = JSON.parse(JSON.stringify(state))
  switch (action.type) {
   
   
    case 'changeCustomerId':
      newState.customerId = action.value
      break
    default:
      break
  }
  return newState
}
export default reducer

上述代码中。我们根据action的type来判断是谁触发了函数,而做出响应的逻辑判断。

模块化封装

当我们有很多模块都使用dispatch触发了一个函数时,我们swicth里面需要写大量代码,代码难以维护。因此,我们对这里的代码进行模块化封装。
src\store\index.ts

import {
   
    legacy_createStore, applyMiddleware } from 'redux'
import {
   
    composeWithDevTools } from 'redux-devtools-extension'
import {
   
    reducer } from './reducer'

// Create a data warehouse
const store = legacy_createStore(reducer, composeWithDevTools(applyMiddleware()))

export default store

src\store\reducer.ts

import {
   
    combineReducers } from 'redux'
import flex from './flexStore'
export type Option<T> = {
   
   
  [actionName: string]: (state: T, value?: any) => void
}
export type Store<T> = {
   
   
  state: T
  action: Option<T>
}
const getModuleReducer = <T>(store: Store<T>) => {
   
   
  // 组合每个子模块的reducer,每个reducer必须返回最新的state对象。combineReducers的参数是合并后的state对象{state1:"value",state2:"value"}
  return (state = store.state, action: {
   
    type: string; value: any }) => {
   
   
    let newState = JSON.parse(JSON.stringify(state))
    Object.keys(store.action).forEach((actionName: string) => {
   
   
      actionName === action.type && store.action[action.type](newState, action.value)
    })
    return newState
  }
}
export const reducer = combineReducers({
   
   
  flex: getModuleReducer(flex)
})

src\store\flexStore.ts

import {
   
    Store } from './reducer'
type State = {
   
   
  customerId: string
}
export default {
   
   
  state: {
   
   
    customerId: ''
  },
  action: {
   
   
    changeCustomerId(state, value) {
   
   
      state.customerId = value
    },
    demo1(state, value) {
   
   },
    demo2(state, value) {
   
   }
  }
} as Store<State>
相关文章
|
3月前
|
存储 JavaScript 前端开发
什么是 Redux?
【8月更文挑战第30天】
47 0
|
6月前
|
JavaScript 前端开发 中间件
vuex/redux的区别
vuex/redux的区别
84 2
|
6月前
|
存储 JavaScript 前端开发
了解 redux 么,说一下 redux 吧
了解 redux 么,说一下 redux 吧
64 0
|
6月前
|
存储 JavaScript 前端开发
Vuex 和 Redux 的区别?
Vuex 和 Redux 的区别?
90 1
|
6月前
|
存储 JavaScript
Vuex和Redux的区别
Vuex和Redux的区别
|
6月前
|
存储 JavaScript API
vuex的使用
vuex的使用
31 0
|
存储 JavaScript 前端开发
什么是Redux?
什么是Redux?
|
6月前
|
存储 JavaScript 前端开发
redux和Vuex的使用与区别
redux和Vuex的使用与区别
71 0
|
JavaScript
Redux中 combineReducers的使用
Redux中 combineReducers的使用
|
存储 JavaScript 前端开发
MobX or Redux ? #81
MobX or Redux ? #81
88 0