带你了解使用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 操作
相关推荐
2401_8791036824 分钟前
24.11.10 css
前端·css
ComPDFKit1 小时前
使用 PDF API 合并 PDF 文件
前端·javascript·macos
yqcoder1 小时前
react 中 memo 模块作用
前端·javascript·react.js
优雅永不过时·2 小时前
Three.js 原生 实现 react-three-fiber drei 的 磨砂反射的效果
前端·javascript·react.js·webgl·threejs·three
神夜大侠5 小时前
VUE 实现公告无缝循环滚动
前端·javascript·vue.js
明辉光焱5 小时前
【Electron】Electron Forge如何支持Element plus?
前端·javascript·vue.js·electron·node.js
柯南二号5 小时前
HarmonyOS ArkTS 下拉列表组件
前端·javascript·数据库·harmonyos·arkts
wyy72935 小时前
v-html 富文本中图片使用element-ui image-viewer组件实现预览,并且阻止滚动条
前端·ui·html
前端郭德纲6 小时前
ES6的Iterator 和 for...of 循环
前端·ecmascript·es6
王解6 小时前
【模块化大作战】Webpack如何搞定CommonJS与ES6混战(3)
前端·webpack·es6