您当前的位置: 首页 > 技术文章 > 前端开发

react3-Redux

作者: 时间:2022-06-16阅读数:人阅读

Redux

  1. 状态管理器
  2. 集中式管理应用中的状态数据,以一种可预测的方式更新状态数据
  3. react-redux 绑定库官网
    redux 与 react 没有任何直接关系,所以在 react 中要使用 redux 进行状态管理,通常还需要额外的绑定库:react-redux

概念

  1. store:仓库,是一个容器,主要用于集中管理应用中的状态

  2. state:状态,是各组件需要共享的状态数据

  3. action:是一个普通对象,通常用于描述发生了什么。这个对象中一般有两个属性:type 和 payload

  4. action creator:action 创建函数,是一个函数结构,主要用于创建 action 对象,以实现 action 的复用

  5. reducer:是用于同步更新状态数据的纯函数。该函数以 state 和 action 作为参数,返回新的 state 状态数据。函数签名是:(state, action) => newState

    注:纯函数
    返回值依赖于参数
    函数主体内部不产生任何副作用
    
  6. Reducer 必需符合以下规则:

  • 仅使用 state 和 action 参数计算新的状态值
  • 禁止直接修改 state。必须通过复制现有的 state 并对复制的值进行更改的方式来做 不可变更新(immutable updates)
  • 可使用lodash来实现深拷贝
  • 禁止任何异步逻辑、依赖随机值或导致其他“副作用”的代码
  1. reducer 函数内部的逻辑通常遵循以下步骤:
  • 检查 reducer 是否关心这个 action
  • 如果是,则复制 state,使用新值更新 state 副本,然后返回新 state,否则,返回原来的 state 不变
  • dispatch:是一个函数,传递 action 作为参数,以调用到 reducer 进行状态更新(在组件中不能直接调用 reducer() 进行状态更新,注reducer() 函数的调用是封装在 dispatch() 函数体内部实现的。)
  • selector:是一个函数,用于从 store 的 state 状态树中提取片段。

三大原则

单一数据源

整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中

State 是只读的

唯一改变 state 的方法就是触发 action(即调用 dispatch(action) 方法),action 是一个用于描述已发生事件的普通对象

使用纯函数来执行修改

为了描述 action 如何改变 state tree ,你需要编写 reducers

使用

  1. 安装
  • $ npm i redux@4.1.2 react-redux@7.2.6
  • $ yarn add redux@4.1.2 react-redux@7.2.6
  1. 创建 reducer
  • 创建.src/actions/ constants.js目录
/** action type 的取值 */
export const ADD_TO_CART = Symbol('add_to_cart')
  • 创建 action creator
    创建 ./src/actions/cart.js 目录,定义 action creator(action创建函数),如:
/**
 * 定义 action creator (action创建函数),用于创建 action 对象,以便于复用 action 对象
 */

import { ADD_TO_CART } from "./constants"

/**
 * 用于创建添加到购物车时使用的 action 对象
 */
export const addToCartAction = (product) => {
  return {
    type: ADD_TO_CART,
    payload: product,
  }
}
  • 创建 ./src/reducers/cart.js 目录,定义 reducer 函数,如:
/**
 * 实现购物车状态数据管理
 */

import _ from 'lodash'
import { ADD_TO_CART, REMOVE_FROM_CART } from "../actions/constants"

/**
 * 初始状态数据
 */
const initialState = {
  cart: [],
}

/**
 * reducer 函数,是一个纯函数,用于同步更新状态数据
 * @param {*} state 旧状态数据
 * @param {*} action action对象,有 type 和 payload 属性 
 * @returns 返回新的状态数据
 */
const cartReducer = (state = initialState, { type, payload }) => {

  /** 对 state 进行深克隆 */
  const copyState = _.cloneDeep(state)

  /**
   * 使用 switch 多分支选择,来判断当前 action 的动作类型
   */
  switch (type) {
    case ADD_TO_CART: // 添加购物车
      copyState.cart.push(payload)
      return copyState
    case REMOVE_FROM_CART: // 从购物车中删除商品
      copyState.cart = copyState.cart.filter(prod => prod.id !== payload.id)
      return copyState
    default:
      return state
  }
}

export default cartReducer
  • ./src/reducers/index.js将各独立的 reducer 合并为根 reducer,如:
/**
 * 将多个独立的 reducer 合并为一个根 reducer
 */

import { combineReducers } from 'redux'
import cartReducer from './cart'

const rootReducer = combineReducers({
  shoppingCart: cartReducer,
})

export default rootReducer
  • 创建 Store
    创建 ./src/store 目录,定义 Store:
/**
 * 创建 Store 仓库
 */

import { createStore } from 'redux'
import rootReducer from '../reducers'

/**
 * 基于根 reducer 来创建 store
 */
const store = createStore(rootReducer)

export default store
  • 入口文件.src/index.js组件中连接 Redux 的 Store
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import {Provider} from "react-redux";
import store from "./store";

ReactDOM.render(
 <Provider store={store}>
         <App/>
 </Provider>,
  document.getElementById('root')
)
  • 文件中使用
import React from 'react'
import {useDispatch, useSelector} from "react-redux"; // 引入并结构出useDispatch(使用方法,改变数据)useSelector(拿到数据)
impot {addToCartActio} fron "../actions/cart.js"

function React() {
  const dispatch=useDispatch()
  const cart=useSelector(state=>state.shoppingCart.cart) // 格式一个回调函数,state.空间名字.仓库数据名字
  const clickHandler=()=>{
  		dispatch(addToCartAction({id:0,title:'商品信息'})) // 触发的actions事件
  }
  return (
    <div onClick={clickHandler}>react</div>
  )
}
export default React

异步任务

  1. 处理异步任务需要三方包
  • yarn add redux-thunk
  1. 在store中引入
import {createStore,applyMiddleware} from "redux";
import logger from 'redux-logger' // 记录仓库状态数据
import thunk from 'redux-thunk' // 异步仓库任务处理
import rootReducer from "../reducers/index"

const store = createStore(rootReducer,applyMiddleware(logger,thunk))
export default store
  1. 在需要异步处理的任务中写法,如actions中登录网络请求
import {LOGIN_SUCCESS,LOGIN_FAILED,LOGIN_RESET} from '../constants/action-types'
import {postLogin} from '../api/user'

export const loginSuccessAction=info=>{
    return {
        type:LOGIN_SUCCESS,
        payload:info,
    }
}
// 重置
export const loginResetAction=()=>{
    return{
        type: LOGIN_RESET,
    }
}
// 异步请求登录网络
export const loginAsyncAction=(info)=>{
    /**
     * 返回的这个函数,会自动被 redux-thunk 中间件调用执行。
     * 在调用执行这个函数时,会自动传递 dispatch 作为参数。
     * 不要求返回的这个函数保持纯净(即可以包含异步逻辑)
     */
    return async dispatch=>{
        const {status,data}=await postLogin(info)
        if(status===200){ // 登录成功
            dispatch(loginSuccessAction(data))
            return true
        }else { // 登录失败
            dispatch({
                type:LOGIN_FAILED
            })
            return false
        }
    }

}

本站所有文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:licqi@yunshuaiweb.com

加载中~
如果您对我们的成果表示认同并且觉得对你有所帮助可以给我们捐赠。您的帮助是对我们最大的支持和动力!
捐赠我们
扫码支持 扫码支持
扫码捐赠,你说多少就多少
2
5
10
20
50
自定义
您当前余额:元
支付宝
微信
余额

打开支付宝扫一扫,即可进行扫码捐赠哦

打开微信扫一扫,即可进行扫码捐赠哦

打开QQ钱包扫一扫,即可进行扫码捐赠哦