一,介绍

React-Redux 是沟通 React 和 Redux 的桥梁,它主要功能体现在如下两个方面:

  1. 在根组件中接受 Redux 的 Store,并把它合理分配到所需要的组件中。
  2. 组件实例订阅 Store 中 state 的改变,促使消费对应的 state 的组件更新。
安装:
npm install --save react-redux

二,使用

React-Redux中提供了一个重要的Provider组件和一个高阶组件connect。
1,Provider
redux 提供给react数据层,但是数据可能会被很多组件使用,provider就可以把redux中提供的store在全局中注入。其作用就是保存redux中的store,分配给所有有需要store中数据的子组件。
用法:

export default function Root() {
  return (
    <Provider store={Store}>
      <Index />
    </Provider>
  );
}

2,connect
connect可以理解为Provider的消费者。可以利用connect 提供的功能,做数据获取,数据通信,状态派发等操作。
connect高价组件调用后,组件将拥有以下功能:
1,能够从props中获取改变Store中state的方法:Store.dispatch
2,如果 connect 有第一个参数,那么会将 redux Store state 中的数据,映射到当前组件的 props 中,子组件可以使用消费。
3,当需要的Store中的 state ,有变化的时候,会通知当前组件更新,重新渲染视图。
用法:

function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)

参数mapStateToProps:对需要使用Store中state的业务组件,将Store中的数据映射到该业务组件中,Store中的state改变触发业务组件中的props改变,对应业务组件的视图会更新。当没有该参数时,当前业务组件不会被订阅
用法:

const mapStateToProps = (state) => ({ number: state.number });

参数mapDispatchToProps: 将redux 中的 dispatch 方法,映射到业务组件的 props 中。

const mapDispatchToProps = (dispatch) => {
  return {
    numberAdd: () => dispatch({ type: "ADD" }),
    setInfo: () => dispatch({ type: "SET" })
  };
};

dispatch分别会调用reducer中对应type的操作。

参数mergeProps:

  • stateProps , state 映射到 props 中的内容
  • dispatchProps, dispatch 映射到 props 中的内容。
  • ownProps 组件本身的 props

用法:

(stateProps, dispatchProps, ownProps) => Object

正常情况下,如果没有这个参数,会按照如下方式进行合并,返回的对象可以是,可以自定义的
合并规则,还可以附加一些属性。
{ ...ownProps, ...stateProps, ...dispatchProps }
参数options: 类型为对象传入

context?: Object, // 自定义上下文
 pure?: boolean, // 默认为 true , 当为 true 的时候 ,除了 mapStateToProps 和 props ,其他输入或者state 改变,均不会更新组件。
 areStatesEqual?: Function, // 当pure true , 比较引进store 中state值 是否和之前相等。 (next: Object, prev: Object) => boolean
 areOwnPropsEqual?: Function, // 当pure true , 比较 props 值, 是否和之前相等。 (next: Object, prev: Object) => boolean
 areStatePropsEqual?: Function, // 当pure true , 比较 mapStateToProps 后的值 是否和之前相等。 (next: Object, prev: Object) => boolean
 areMergedPropsEqual?: Function, // 当 pure 为 true 时, 比较 经过 mergeProps 合并后的值 , 是否与之前等 (next: Object, prev: Object) => boolean
 forwardRef?: boolean, //当为true 时候,可以通过ref 获取被connect包裹的组件实例。

三,示例

1,新建store文件
在项目目录src下新建Redux的Store目录(store文件夹)并新建index.js和reducer.js文件
在index.js中我们创建Store数据储存仓库

import { createStore, applyMiddleware, compose } from "redux"; // 引入createStore方法
import reducer from "./reducer";

const store = createStore(reducer); // 创建数据存储仓库

export default store;

创建完Store,我们可以先在项目index.js中先引入,使用Provide派发

import { StrictMode } from "react";
import ReactDOM from "react-dom";

// import App from "./React-redux-demo/demo02";
import CompA from "./React-redux-demo/compA";
import CompB from "./React-redux-demo/compB";
import { Provider } from "react-redux";
import store from "./store";
const App = (
  <Provider store={store}>
    {/* <Index /> */}
    <CompA />
    <CompB />
  </Provider>
);
{
  /* <StrictMode>
<App />
</StrictMode>, */
}
const rootElement = document.getElementById("root");
ReactDOM.render(App, rootElement);

创建compA和compB子组件,并在根组件中引入,如上

import React, { useState, useEffect } from "react";
import { connect } from "react-redux";

function ComponentA({ toCompB, compBsay }) {
  const [CompAsay, setCompAsay] = useState("");
  return (
    <div className="box">
      <p>我是组件A</p>
      <div> B组件对我说:{compBsay} </div>
      我对B组件说:
      <input
        placeholder="CompAsay"
        onChange={(e) => setCompAsay(e.target.value)}
      />
      <button onClick={() => toCompB(CompAsay)}>确定</button>
    </div>
  );
}
/* 映射state中CompBsay  */
const CompAMapStateToProps = (state) => ({ compBsay: state.info.compBsay });
/* 映射toCompB方法到props中 */
const CompAmapDispatchToProps = (dispatch) => ({
  toCompB: (mes) => {
    dispatch({ type: "SET", payload: { compAsay: mes } });
  }
});
/* connect包装组件A */
export default connect(
  CompAMapStateToProps,
  CompAmapDispatchToProps
)(ComponentA);

import { Component } from "react";

import { connect } from "react-redux";
class ComponentB extends Component {
  state = { compBsay: "" };
  handleToA = () => {
    this.props.dispatch({
      type: "SET",
      payload: { compBsay: this.state.compBsay }
    });
  };
  render() {
    return (
      <div className="box">
        <p>我是组件B</p>
        <div> A组件对我说:{this.props.compAsay} </div>
        我对A组件说:
        <input
          placeholder="CompBsay"
          onChange={(e) => this.setState({ compBsay: e.target.value })}
        />
        <button onClick={this.handleToA}>确定</button>
      </div>
    );
  }
}
/* 映射state中 CompAsay  */
const CompBMapStateToProps = (state) => ({ compAsay: state.info.compAsay });
export default connect(CompBMapStateToProps)(ComponentB);

在reducer.js中我们创建Store需要储存的State数据

//定义初始state
const defaultState = {
  number: 2,
  info: {
    compAsay: "",
    compBsay: ""
  }
};

//深拷贝
function deepClone(obj) {
  var objClone = Array.isArray(obj) ? [] : {};
  //进行深拷贝的不能为空,并且是对象或者是
  if (obj && typeof obj === "object") {
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (obj[key] && typeof obj[key] === "object") {
          objClone[key] = deepClone(obj[key]);
        } else {
          objClone[key] = obj[key];
        }
      }
    }
  }
  return objClone;
}

export default (state = defaultState, action) => {
  // #reducer里只能接受state 不能改变state
  if (action.type == "SET" && action.payload.compAsay) {
    let newState = deepClone(state);  //深拷贝state
    newState.info.compAsay = action.payload.compAsay;
    return newState;
  }
  if (action.type == "SET" && action.payload.compBsay) {
    let newState = deepClone(state);
    newState.info.compBsay = action.payload.compBsay;
    return newState;
  }
  return state;
};

yuobey
1 声望0 粉丝