带你了解使用Redux、react-redux

redux

介绍

Redux是 JavaScript 状态容器,提供可预测化的状态管理。

在 react 中可以用来集中式管理 react 应用中多个组件共享的状态。

使用场景

  • 某个组件的状态,需要让其他组件可以随时拿到(共享)。

  • 当一个组件需要改变另一个组件的状态(通信)。

使用

npm install --save redux

使用步骤

1、创建 reducer.js 文件,定义 reducer 函数 ,建立初始状态。

js 复制代码
// reducer.js

// 初始化的状态
const defaultState = {
  num: 30,
}
// reducer 函数传入了两个参数 state、action
/*
  state:状态数据
  action:为一个动作对象,有着两个属性 type 和 data
          type:标识属性, 值为字符串, 唯一, 必要属性
          data:数据属性, 值类型任意, 可选属性
          例子:{ type: 'add_number', data: 5}
*/
// reducer 用于初始化状态、加工状态
const reducer = (
  state = defaultState,
  action
) => {
  state = JSON.parse(JSON.stringify(state))
  switch(action.type) {
    case "addOne":
      state.num++;
      break;
    case "addNum":
      state.num += action.value;
      break;
    default:
      break;
  }

  return state;
}

export default reducer;

  

2、创建 index.js 文件,导入 redux 的 legacy_createStore 函数。引入 reducer.js 文件,将其中的 reducer 函数传入到 legacy_createStore 生成 store 对象,并暴露出来。

js 复制代码
// index.js

// import { createStore } from "redux"; // 现已弃用

// legacy_createStore 用于创建 redux 中最为核心的 store 对象
import { legacy_createStore } from "redux";
import reducer from "./reducer"

const store = legacy_createStore(reducer);

export default store

3、在组件中导入 store 并使用。

js 复制代码
// App.js
import React, { Component } from 'react'
import store from './store';


export default class App extends Component {
  componentDidMount() {
    store.subscribe(() => {
      // 借用 state 来调用 render 更新页面。
      this.setState({});
    })
  }
  addOne = ()=> {
    store.dispatch({
      type: 'addOne',
      data: 5
    })
  }
  render() {
      return (
        <div className="App">
          <div>{store.getState().num}</div>
          <button onClick={this.addOne}>+ 1</button>
        </div>
      );
  }
}

此时我们打印 store 可以看到这么一个对象:

  • getState() 获取 state 状态
  • dispatch(action) 修改 store 中的 state 值的唯一途径就是通过调用 dispatch 方法匹配 dispatch 传入的 type 字段从而执行对应匹配 reducer 函数中的逻辑修改 state
  • subscribe(listener) 注册监听器,监听状态里所有数据的变化
  • replaceReducer(reducer) 接受一个 reducer 作为参数,它会替换 store 当前用来计算 state 的 reducer
  • observable 这个函数通常情况下不会使用, 是为了配置具有 observable/reactive 特性的三方库来使用的, 其返回一个对象, 对象中包括订阅方法, 该类似 subscribe 方法

action 对象文件

可以专门创建一个 action 文件,来放置 action 对象。

js 复制代码
// store_action.js
const createAddAction = data => ({ type: 'addNum', data })

export { createAddAction }

使用

js 复制代码
store.dispatch(createAddAction(30))

异步 action

有时候执行的操作涉及接口、定时等异步任务,延时来修改状态。可以由 action 待执行异步任务。

由于 dispatch 传递的值是一个函数,本身是只接受对象值, 所以需要一个中间件来转换,利用 npm i redux-thunk来解决这个问题。

js 复制代码
// store/index.js
// applyMiddleware 用于执行中间件
import { legacy_createStore, applyMiddleware } from "redux";
import reducer from "./reducer"
// 用于支持异步 action
import thunk from "redux-thunk"

const store = legacy_createStore(reducer, applyMiddleware(thunk));

export default store

action 对象文件

js 复制代码
// store_action.js
const createAddAction = data => ({ type: 'addNum', data })
const createAddActionAsync = (data, time) => {
  // store 根据接收的参数,接受的是函数,根据函数的形参去调用相应的dispatch
  return (dispatch) =>{
    setTimeout(()=> {
      dispatch(createAddAction(data))
    }, time)
  }
}

export { createAddAction, createAddActionAsync }

使用

js 复制代码
import { createAddActionAsync } from '../store/store_action'
addNum = ()=>{
    store.dispatch(createAddActionAsync(30))
}

react-redux

react-redux 是 react 专用的插件库,用来简化 react 应用中使用 redux 的操作。

npm install --save react-redux

组件例子

react-redux 将组件分为 容器组件 和 UI组件。 -容器组件 负责管理数据和业务逻辑 -UI组件 负责视图呈现,通过 props 接收数据

App.js 用来传递 store:

js 复制代码
import React, { Component } from 'react'
import Container from './containers/index';
import store  from './store';

export default class App extends Component {
 
  render() {
      return (
        <div className="App">
          123
          // 给容器组件传递 store
          <Container store={store} />
        </div>
      );
  }
}

容器组件 containers.js 可以获取到 App.js 传递 store:

js 复制代码
// containers.js
import uiCom from './components/uiComponents'
// 引入 connect 用于连接 UI组件与 redux
import { connect } from 'react-redux'
// 引入 action ,集中管理 action
import { createAddAction, createJianAction } from '../store/store_action'

// state 相当于 store 状态
function mapStateToProps(state) {
  return {
    n: state
  }
}
// dispatch 可用于修改状态
function mapDispatchToProps(dispatch) {
  return {
    add: (number)=> {
      // dispatch({type: 'addNum', data: number})
      dispatch(createAddAction(number))
    },
    jian: number => dispatch(createJianAction(number))
  }
}
// 使用 connect()()创建并暴露一个容器组件,其中mapStateToProps、mapDispatchToProps用于传给 ui组件,ui组件可以用 props 获取到。
const container = connect(mapStateToProps, mapDispatchToProps)(uiCom)

export default container

UI组件 接收容器组件传递的值:

js 复制代码
import React, { Component } from 'react'

export default class uiCom extends Component {
  addOne = ()=> {
    this.props.add(2)
    console.log(this.props)
  }
  render() {
      console.log('收到的props', this.props)
      return (
        <div className="App">
          <div>{this.props.n.num}</div>
          <button onClick={this.addOne}>+ 1</button>
        </div>
      );
  }
}

props 打印出来的样子

总结

  • 创建 reducer 文件,用于放置状态及操作状态
  • 使用 legacy_createStore 创建出 store 仓库
  • react-redux 让状态传递组件区分 容器组件 和 UI组件,用于简化 redux 操作
相关推荐
仰望星空的小猴子10 分钟前
React18和React19新特性
前端
小码哥_常11 分钟前
Android新航标:Navigation 3为何成为变革先锋?
前端
SuperEugene12 分钟前
Vue状态管理扫盲篇:状态管理中的常见坑 | 循环依赖、状态污染与调试技巧
前端·vue.js·面试
骑着小黑马13 分钟前
从 Electron 到 Tauri 2:我用 3.5MB 做了个音乐播放器
前端·vue.js·typescript
aykon13 分钟前
DataSource详解以及优势
前端
Mintopia13 分钟前
戴了 30 天智能手环后,我才发现自己一直低估了“睡眠”
前端
leolee1814 分钟前
react redux 简单使用
前端·react.js·redux
仰望星空的小猴子15 分钟前
常用的Hooks
前端
天才熊猫君15 分钟前
Vue Fragment 锚点机制
前端
米丘16 分钟前
Git 常用操作命令
前端