React redux、react-redux的基本使用(笔记)

文章目录

      • 1. redux 是什么
      • 2. 什么时候使用 redux
      • 3. redux 安装与使用
        • 3.1 安装
        • 3.2 完整使用
        • 3.3 异步 action
      • 4. react-redux 的理解
      • 5. react-redux 安装与使用
        • 5.1 安装
        • 5.2 连接容器组件和UI组件
        • 5.3 基本使用
      • 6. react-redux 优化
        • 6.1 简写 mapDispatchToProps
        • 6.2 使用 Provider 组件
        • 6.3 合并UI组件和容器组件
      • 7. 数据共享
        • 7.1 文件结构

1. redux 是什么

  • redux 是一个专门用于做状态管理的 JS 库 (不是 react 插件库)
  • 它可以用在各种项目中,但是基本与 react 配合使用
  • 作用:集中式管理 react 应用中多个组件共享的状态

2. 什么时候使用 redux

  • 多个组件依赖于同一状态
  • 多个组件所依赖的数据都是相互影响的,组件 A 中共享数据的更改,组件 B 中共享的同一数据默认也会改

3. redux 安装与使用

3.1 安装
// 使用 npm 安装
npm i redux
3.2 完整使用
  • 创建 redux/store.js 文件,存放数据

    // 用于创建一个 store
    import { createStore } from "redux"
    // 用于 Count 组件服务的 reducer
    import countReducer from "./count_reducer.js"
    
    export default createStore(countReducer)
    
  • 创建 redux/count_reducer.js 文件,处理数据

    import { ADD, SUB } from "./constant.js"
    
    // preState:表示初始值,或前一次状态的值
    export default function countReducer(preState = 0, action){
      // action:它是一个对象,包含了方法和数据
      let { type, data } = action
      switch(type) {
        case ADD:
      	  return preState + data
        case SUB:
      	  return preState - data
        default:
          return preState
         // 必须要返回一个新值或初始值
      }
    }
    
  • 创建 redux/count_action.js 文件,提供方法

    import { ADD, SUB } from "./constant.js"
    
    // action 需要返回一个对象,type:方法名、data:数据
    export const addAction = data => ({ type: ADD, data })
    export const subAction = data => ({ type: SUB, data })
    
  • 创建 redux/constant.js 文件,命名空间

    // 因为 type 方法名称在多处都会使用到,这样写便于管理,还可以防止程序员写错
    export const ADD = "add"
    export const SUB = "sub"
    
  • 组件中使用 store

    import { Component } from "react";
    import store from "./src/redux/store.js"
    import { addAction, subAction } from "./src/redux/count_action.js"
    
    export default class Count extends Component {
      componentDidMount() {
        /*
          store 中的值发生了改变,并不会调用自动 render
          当 store 中的值发生了改变,store.subscribe 会触发回调,然后使用 this.setState 强制调用 render
          这样写有一点不好,就是每在一个组件使用一次,都需要再去写一遍,可以直接在入口文件中使用
          这样只要有一个组件中的 redux 值发生了改变,就会更新视图
          store.subscribe(() => {
            ReactDOM.render(, document.getElement("root"))
          })
        */
        store.subscribe(() => {
          this.setState({})
        })
      }
     
      add = (data) => {
        // dispatch 会触发 reducer 函数(这里指 countReducer 函数)
        store.dispatch(addAction(data))
      }
    
      sub = (data) => {
        store.dispatch(subAction(data))
      }
    
      render() {
        return (
          // getState 使用数据,store 本身是一个对象
          <div>{ store.getState() }</div>
        )
      }
    }
    
3.3 异步 action
// 当 action 为函数时,它将会成为一个异步 action

import { createStore, applyMiddleware } from "redux"
// 引入 redux-thunk,用于支持异步 action
import thunk from "redux-thunk"

// 此时暴露时,需要执行中间件
export default createStore(countReducer, applyMiddleware(thunk))
// 这个时候写 action 时,就可以返回函数了
// 异步函数里面还是调用的同步函数
export const addAsyncAction = (data, time) => {
  return (dispath) => {
    setTimeout(() => {
      dispath(addAction(data))
    },time)
  }
}
store.dispatch(addAsyncAction(data, 300))

4. react-redux 的理解

  • react-redux 是对 redux 的封装,成为了 react 的一个插件库
  • react-redux 中所有的容器组件都应该包裹一个UI组件,他们为父子关系
  • 只有容器组件才能调用 react-redux 中的方法,store.getState()、store.dispath(action)
  • UI组件的状态和方法,只能通过 props 传递

5. react-redux 安装与使用

5.1 安装
npm i react-redux
5.2 连接容器组件和UI组件
  • 容器组件,连接容器组件和UI组件

    // count 容器组件,容器组件要写在 container 文件下,UI组件要写在 component 文件下
    import CountUI from "./component/Count"
    // 用于连接 UI 和 store,但此时只连接了 UI
    import { connect } from "react-redux"
    
    export default connect()(CountUI) // 有了 connect 函数不需要在手动检测数据的变化了
    
  • 引入容器组件,连接容器组件和 store

    // 使用组件时,要使用容器组件
    import Count from "./container/Count"
    // 使用时需要把 store 作为 prop 值传过去
    import store from "./redux/store"
    
    export default class Demo extends Componet {
      render(){
        return <Count store={store}></Count>
      }
    }
    
  • UI组件

    // 正常写页面就可以了
    
5.3 基本使用
// 容器组件
import { connect } from "react-redux"

import CountUI from "../component/Count"
import { addAction } from "../redux/count_action"

// 该函数返回一个存状态的对象,会把该对象的值映射到 CountUI 组件的 props 中
function mapStateToProps(state){
  return {
    // state ==> store.getState()
    count: state
  }
}
// 该函数返回一个存方法的对象,映射到 props 中
function mapDispatchToProps(dispatch){
  return {
    // dispatch ==> store.dispath
    add: (data) => {
      dispatch(addAction(data))
    }
  }
}

// 此时连接了 UI 和 store
export default connect(mapStateToProps, mapStateToProps)(CountUI)
// UI组件
export default class CountUI extends Componet {
  return(){
    console.log(this.porps) // {store: {…}, count: 0, add: ƒ},这里也可以拿到 store 对象
  }
}

6. react-redux 优化

6.1 简写 mapDispatchToProps
// 优化前
import { connect } from "react-redux";

import countUI from "../components/CountUI.jsx";
import { addAction, subAction, addAsyncAction } from "../redux/count_action";

export default connect(
  (state) => ({
    count: state,
  }),
  // 当 mapDispatchToProps 为对象时,可以直接把函数赋值过去
  {
    add: addAction,
    sub: subAction,
    addAsync: addAsyncAction,
  }
)(countUI);
6.2 使用 Provider 组件
import React from "react";
import reactDOM from "react-dom";
import { Provider } from "react-redux";

import store from "./redux/store";
import App from "./App.jsx";

// 在这里使用 Provider 组件传入 store 值,使后续的所有组件都不需要再次传入 store
reactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById("root")
);
6.3 合并UI组件和容器组件
import React, { Component } from "react";
import { connect } from "react-redux";

import { addAction, subAction, addAsyncAction } from "../redux/count_action";

// UI组件部分
class countUI extends Component {
  add = () => {
    let { value } = this.selectNode;
    this.props.add(Number(value));
  };

  sub = () => {
    let { value } = this.selectNode;
    this.props.sub(Number(value));
  };

  addAsync = () => {
    let { value } = this.selectNode;
    this.props.addAsync(Number(value), 500);
  };
  render() {
    let { count } = this.props;
    return (
      <div>
        <div>
          <h1>{count}</h1>
          <select ref={(curNode) => (this.selectNode = curNode)}>
            <option>1</option>
            <option>2</option>
            <option>3</option>
          </select>
          <button onClick={this.add}>点我加</button>
          <button onClick={this.sub}>点我减</button>
          <button onClick={this.addAsync}>异步加</button>
        </div>
      </div>
    );
  }
}

// connect 连接部分
export default connect (
  (state) => ({
    count: state,
  }),
  {
    add: addAction,
    sub: subAction,
    addAsync: addAsyncAction,
  }
)(countUI);

7. 数据共享

7.1 文件结构
|-- redux 				// 数据处理的总文件夹
  |-- reducers			// 集中管理reducer
	|-- demo1.js		// 第一个reducer
	|-- demo2.js		// 第二...
	|-- index.js		// reducers的汇总
  |-- actions			// 集中管理action
	|-- demo1.js		// 第一个action
	|-- demo2.js		// 第二...
  |-- constant.js		// 命名空间
  |-- sotre.js			// 主文件,存放状态

你可能感兴趣的:(react,react.js,javascript,前端)