React-redux

redux

在这里插入图片描述

起源

在这里插入图片描述

2014年 Facebook 提出了 Flux 架构的概念,采用 单向数据流 思想。
在这里插入图片描述

2015年,Redux 出现,将 Flux 与 函数式编程 结合一起,很短时间内就成为了最热门的状态管理架构。

Redux 概述

  • yarn add redux

在这里插入图片描述

Redux 是 JavaScript 应用的可预测状态容器,用来集中管理状态。
特点:集中管理、可预测、易于测试、易于调试、强大的中间件机制满足你所有需求。
注意:redux 是一个独立于 react 的库,可以配合任何 UI 库/框架来使用。

redux的三大原则

单一数据源

State是只读的

使用纯函数来执行修改

什么情况下需要使用redux

  1. 总体原则: 大型项目状态管理复杂才用

  2. 某个组件的状态,需要共享

  3. 某个状态需要在任何地方都可以拿到

  4. 一个组件需要改变全局状态

  5. 一个组件需要改变另一个组件的状态

三个核心概念

计数器案例:点击 +1 按钮,数值加1(React 关注 UI,Redux 关注 state)。
计数器案例的 state: { count: 0 } 。
在这里插入图片描述

  • Action(“砖”家):描述要执行的行为动作,比如要让计数器的值加1(提出想法)。
  • Reducer(劳动者):接收 Action 完成该动作,比如完成值加1得到新状态 { count: 1 }(实现想法)。
  • Store(管理者):是 Action 和 Reducer 的桥梁,将 Action 传递给 Reducer。

在这里插入图片描述

action

  • Action(“砖”家):描述要执行的行为动作
  • action 是一个原生 JavaScript 对象。
  • 作用:描述要执行的行为动作,提供完成该动作需要的数据。比如:计数器案例 +1 就是一个动作
  • 约定1:必须提供 type 属性,用于描述动作类型。
  • 约定2:type 属性的值是字符串,约定使用全大写字母。
  • 约定3:可以提供其他属性,提供完成该动作需要的数据。
  • 简化操作:使用函数来创建 action,将该函数叫做 action creator。
{ type: 'INCREMENT', data: 2, }

// todo app,添加任务的action:
{ type: 'ADD_TODO', text: '学习Redux' }
// action creator:
const increment = () => ({ type: 'INCREMENT' })
// 创建action
increment()

reducer

  • Reducer(劳动者):接收 Action 完成该动作
  • reducer 是一个函数。
  • 作用:接收 action 和 state(初始 state), 完成该行为动作,并返回新 state。
  • 代码解释:(state, action) => newState。
  • 约定:不要直接修改 state,而是,根据当前 state 得到新的 state。
  • 注意:reducer 应该是一个纯函数(同样的输入,必定得到同样的输出),不要有修改参数、调用 Math.random() 等不纯的操作。
const counter = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1 // state++ 表示直接修改当前 state
    default:           // 必须得有!默认返回当前 state
      return state
  }
}

store

  • Store(管理者):是 Action 和 Reducer 的桥梁,将 Action 传递给 Reducer
  • Redux 的 state 仓库。一个 redux 应用只有一个 store。
  • 作用:将 action 和 reducer 组合到一起。
  • 职责:
    • 1 提供整个应用的 state
    • 2 提供 dispatch 方法,用来触发 action
    • 3 提供 getState 方法,用来获取整个应用的 state
    • 4 提供 subscribe 方法,监听 state 变化。
import { createStore } from 'redux'
import counter from './reducer'
// 接收 reducer 作为参数,创建 store
const store = createStore(counter)
store.getState() // 获取state
store.dispatch() // 触发 action
const unsubscribe = store.subscribe(() => {}) // 监听 state 变化
//调用unsubscribe()取消监听state变化

redux的基本使用

1.安装

yarn add redux

2.导入createStore函数

  • 在js文件中从redux包里导入createStore函数
import { createStore } from "redux"

3.创建store,将reducer传入到store中

const store = createStore(reducer)

4.定义reducer函数

  • 要接收两个参数: state, action
  • 注意:在定义reducer的时候,通过es6语法设置默认值的方式,初始化state的值
  • state表示最新的数据, 注意: 一般在定义reducer的时候,state都要先给一个初始值
  • action表示需求
function reducer(
  state = {
    count: 0,
    msg: "劳斯宾利法拉利",
  },
  action
) {
  switch (action.type) {
    case "ADD":
      return {
        ...state,
        count: state.count + action.data,
      };
    default:
      return state;
  }
}

store.getState()

  • 获取到redux中state里面存储的所有的数据
console.log(store.getState())

在这里插入图片描述

store.subscribe()

  • 调用subscribe,监听state的变化
  • 注意:要在dispatch之前调用
store.subscribe(() => {
  console.log(store.getState());
});

在这里插入图片描述

store.diapatch()

  • 分发action
  • 调用这个方法,reducer函数就会执行
store.dispatch({ type: "ADD", data: 1 });
store.dispatch({ type: "ADD", data: 2 });
store.dispatch({ type: "ADD", data: 3 });
store.dispatch({ type: "ADD", data: 4 });

redux的内部执行原理

redux内部会创建一个action {type: “@@redux/INIT8.v.s.i.j.j”}
目的是让reducer中执行默认的返回值,从而拿到state的初始化值

  • reducer函数在创建store的时候,会调用一次.这次是为了初始化redux中state的数据
  • 后面每一次调用dispatch的时候,reducer也会执行.这里执行是为了修改redux中state的数据
// 1.创建store
const store = createStore(reducer);

// 2.创建reducer函数
function reducer(
  state = {
    count: 0,
    msg: "劳斯宾利法拉利",
  },
  action
) {
  console.log(state, action);
  switch (action.type) {
    case "ADD":
      return {
        ...state,
        count: state.count + action.data,
      };
    default:
      return state;
  }
}

store.dispatch({ type: "ADD", data: 1 });
store.dispatch({ type: "ADD", data: 2 });
store.dispatch({ type: "ADD", data: 3 });
store.dispatch({ type: "ADD", data: 4 });

在这里插入图片描述

react-redux

在这里插入图片描述
在这里插入图片描述

  • Redux 只能用来管理应用的 state。
  • 如果要配合 react 使用,需要借助 react-redux 这个绑定库。

核心API

Provider 组件:

  • 用来包裹整个 React 应用,接收 store 属性,为应用提供 state 和 操作 state 的方法。

connect 函数:

  • 连接 Redux 和 React 组件,为被包裹的组件提供 state 和 操作 state 的方法。
    组件中通过 props 获取 Redux store 的内容。
import { Provider } from 'react-redux'
<Provider store={store}>
  <App />
</Provider>
connect()(Counter)
// mapStateToProps 函数:提供组件用到的state,作为组件的props,传递给 Counter 组件
// mapDispatchToProps 函数:提供组件用到的操作state的方法,作为组件的props ,传递给 Counter 组件
//注意: 这两个参数是函数,一定要有返回值(返回值是对象)并且都是可选的(可以不传) 
connect(mapStateToProps, mapDispatchToProps)(Counter)

使用步骤

1.yarn add react-redux

  • 安装react-redux包
yarn add react-redux

2.导入Provider组件

import { Provider } from "react-redux"

3.使用Provider包裹

  • 使用Provider组件作为React应用的根组件,包裹整个应用
  • 可以在App根组件包裹其它组件,也可以直接在index.js文件中直接包裹App
import React, { Component } from "react";

// 导入Provider
import { Provider } from "react-redux";
// 导入store
import store from "./redux/store"

// 最终用的是WithCounter
import WithCounter from "./Counter"

export default class App extends Component {
  render() {
    return (
      // 所以要创建store对象,在src下面创建redux文件夹,所有redux代码都写在redux文件夹下
      // 创建store.js
      <Provider store={store}>
        <div>
            <WithCounter></WithCounter>
        </div>
      </Provider>
    );
  }
}

4.为Provider添加store属性

  • 将redux的store作为Provider组件的store属性的值
import { createStore } from "redux";

import reducer from "./reducer"
const store = createStore(reducer);

export default store;

5.导入Connect函数

  • 导入Connect函数(将React组件和Redux store链接在一起)
// 在Counter组件中,如果想用redux中的数据
// 1.先导入connect函数
import { connect } from "react-redux";

6.使用Connect函数,包装React组件

  • 使用connect函数,包装React组件
connect内部原理
    //connect内部原理,第二次调用才是那个组件
    function Connect(){
        return function(){
            return class extends Component{

            }
        }
    }
第一次调用 传第一个参数
import React, { Component } from "react";
// 在Counter组件中,如果想用redux中的数据
// 1.先导入connect函数
import { connect } from "react-redux";

class Counter extends Component {
  handleADD = () => {
    // react中无法直接修改redux中的数据.需要调用dispatch
    // 调用dispatch要传入一个action
    this.props.dispatch({ type: "ADD", data: 2 });
  };
  render() {
    console.log(this.props);
    return (
      <>
        <div>{this.props.count}</div>
        <button onClick={this.handleADD}>type:"ADD"2</button>
      </>
    );
  }
}

// 2.然后调用connect得到一个高阶组件,这个高阶组件会将数据传给我们定义的react组件
/* 
    注意:如果connect函数第一次调用不传任何参数,我们react的组件只能通过props拿到第一个dispatch方法,但是拿不到数据

    如果想要获取redux中的数据.需要定义一个函数,传入到connect第一次调用中,在connect函数底层会调用这个函数,调用这个函数时候把redux最新数据传到这个函数形参上
*/

/* 
    这个state就是redux中最新的state
    这个mapStateToProps这个函数,第一次执行connect的时候调用,将redux中的数据传给react组件
    后面当redux的数据发生变化了,connect底层还会再次调用这个函数,将最新的数据传给react组件
*/
const mapStateToProps = (state) => {
  // 这个return的对象怎么写的,react组件的props里面就是有什么数据
  // 这个state接收的是所有的数据,想要哪个取哪个就行
  console.log(state);
  return {
    count: state.count,
  };
};

const WithCounter = connect(mapStateToProps)(Counter);
export default WithCounter;

在这里插入图片描述
在这里插入图片描述

第一次调用,传第二个参数
import React, { Component } from "react";
// 在Counter组件中,如果想用redux中的数据
// 1.先导入connect函数
import { connect } from "react-redux";

class Counter extends Component {
  handleADD = () => {
    // react中无法直接修改redux中的数据.需要调用dispatch
    // 调用dispatch要传入一个action
    // this.props.dispatch({ type: "ADD", data: 2 });
    this.props.onADD();
  };
  render() {
    console.log(this.props);
    return (
      <>
        <div>{this.props.count}</div>
        <button onClick={this.handleADD}>type:"ADD"2</button>
      </>
    );
  }
}

// 2.然后调用connect得到一个高阶组件,==这个高阶组件会将数据传给我们定义的react组件==

const mapStateToProps = (state) => {
  // 这个return的对象怎么写的,react组件的props里面就是有什么数据
  // 这个state接收的是所有的数据,想要哪个取哪个就行
  console.log(state);
  return {
    count: state.count,
  };
};

// 当第一次调用connect的时候传入第二个参数,会发现dispatch没有了,取而代之是我们自定义的函数
// 尽量这样使用,在react里面看不见redux,以后不再使用redux也好处理
const mapDispatchToProps = (dispatch) => {
  return {
    onADD() {
      dispatch({ type: "ADD", data: 2 });
    },
  };
};

const WithCounter = connect(mapStateToProps, mapDispatchToProps)(Counter);
export default WithCounter;

在这里插入图片描述

第二次调用
import React, { Component } from 'react'
// 在Counter组件中,如果想用redux中的数据
// 1.先导入connect函数
import {connect} from "react-redux"


class Counter extends Component {  
    render() {
        console.log(this.props)
        return (
            <div>
                {"使用redux的数据"}
            </div>
        )
    }
}

// 2.然后调用connect得到一个高阶组件,这个高阶组件会将数据传给我们定义的react组件
const WithCounter = connect()(Counter)
export default WithCounter

在这里插入图片描述

7.React组件获取Redux中的state

  • 在React组件中,通过props可以获取到Redux store中的state
//导入provider和connect
import { Provider, connect } from 'react-redux'

// 定义的函数组件
function Counter(props) {
  console.log(props) //默认可以获取到dispatch方法
  return (
    <div>
      <div>{props.count}</div>
      <button onClick={() => props.onincrement()}>+1</button>
    </div>
  )
}
//使用connect包装Counter组件
const WithCounter = connect(
  mapState,
  mapDispatch
)(Counter)

//connect要用的第一个参数 
// state是redux中的state
const mapState = state => {
  return {
      // 这里return的内容就是react组件中props接收到的数据
    count: state
  }
}
//connect要用的第二个参数
//dispatch 是redux中的dispath
const mapDispatch = dispatch => {
  return {
       // 这里return的内容就是react组件中props接收到的数据
    onincrement() {
      dispatch({ type: 'INCREMENT' })
    }
  }
}
//最终使用包装后的组件
ReactDOM.render(
  <Provider store={store}>
    <WithCounter></WithCounter>
  </Provider>,
  document.getElementById('root')
)

两种类型的组件/React和Redux分离

在这里插入图片描述

这样实现了redux与react分开书写,方便维护和后期更换别的库

展示组件(UI组件)

== React中的组件==

  • 可以理解为: 不跟 redux 关联的组件(要传入connect() 中的组件 )
  • 特点: 提供了组件的结构和样式
import React, { Component } from "react";

export default class Counter extends Component {
  handleADD = () => {
    // react中无法直接修改redux中的数据.需要调用dispatch
    // 调用dispatch要传入一个action
    // this.props.dispatch({ type: "ADD", data: 2 });
    this.props.onADD();
  };
  render() {
    console.log(this.props);
    return (
      <>
        <div>{this.props.count}</div>
        <button onClick={this.handleADD}>type:"ADD"2</button>
      </>
    );
  }
}

容器组件

调用完connect之后得到的withXXX

  • 可以理解为: 跟 redux 密切关联的组件( 调用 connect() 之后得到的组件 )
  • 特点: 专门与 redux 进行交互
// 在Counter组件中,如果想用redux中的数据
// 1.先导入connect函数
import { connect } from "react-redux";

// 引入展示组件counter
import Counter from "../Counter";

// 2.然后调用connect得到一个高阶组件,这个高阶组件会将数据传给我们定义的react组件
const mapStateToProps = (state) => {
  // 这个return的对象怎么写的,react组件的props里面就是有什么数据
  // 这个state接收的是所有的数据,想要哪个取哪个就行
  console.log(state);
  return {
    count: state.count,
  };
};

// 当第一次调用connect的时候传入第二个参数,会发现dispatch没有了,取而代之是我们自定义的函数
// 尽量这样使用,在react里面看不见redux,以后不再使用redux也好处理
const mapDispatchToProps = (dispatch) => {
  return {
    onADD() {
      dispatch({ type: "ADD", data: 2 });
    },
  };
};

const WithCounter = connect(mapStateToProps, mapDispatchToProps)(Counter);
export default WithCounter;

react-redux 优化/简写

actions/actionCreator

  • 在redux文件夹下创建actions.js
/* 
    需求1:数字增加1 {type:"ADD",data:1}
    需求2:数字增加2 {type:"ADD",data:2}
*/
// 将action对象封装起来  统称为actionCreator
function Add(data) {
  return {
    type: "ADD",
    data: data,
  };
}

export {Add}
  • 在容器组件中调用
// 在Counter组件中,如果想用redux中的数据
// 1.先导入connect函数
import { connect } from "react-redux";

// 引入展示组件counter
import Counter from "../Counter";

// 导入action
import { Add } from "../redux/actions";

const mapStateToProps = (state) => {
  console.log(state);
  return {
    count: state.count,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    onADD() {
      //   dispatch({ type: "ADD", data: 2 });
      dispatch(Add(2));
    },
  };
};

const WithCounter = connect(mapStateToProps, mapDispatchToProps)(Counter);
export default WithCounter;

在这里插入图片描述

constants

  • 在redux文件夹下面创建一个constants.js
// 定义常量,方便后期统一维护管理
export const ADD = "ADD"
  • actions使用
/* 
    需求1:数字增加1 {type:"ADD",data:1}
    需求2:数字增加2 {type:"ADD",data:2}
*/
// 将action对象封装起来  统称为actionCreator

import { ADD } from "../redux/constants";
function Add(data) {
  return {
    // type: "ADD",
    type: ADD,
    data: data,
  };
}

export { Add };

  • 更改action
/* 
    需求1:数字增加1 {type:"ADD",data:1}
    需求2:数字增加2 {type:"ADD",data:2}
*/
// 将action对象封装起来  统称为actionCreator

// 引入常量
import { ADD } from "../redux/constants";

function Add(data) {
  return {
    // type: "ADD",
    type: ADD,
    data: data,
  };
}

export { Add };

  • 更改reducer
// 导入常量
import { ADD } from "../redux/constants";

export default function reducer(
  state = {
    count: 0,
    msg: "我爱你中国",
    arr: [1, 2, 3, 4],
  },
  action
) {
  switch (action.type) {
    // case "ADD":
    case ADD:
      return {
        ...state,
        count: state.count + action.data,
      };
    default:
      return state;
  }
}

connect参数里函数简写

// 在Counter组件中,如果想用redux中的数据
// 1.先导入connect函数
import { connect } from "react-redux";

// 引入展示组件counter
import Counter from "../Counter";

// 导入action
import { Add, Less } from "../redux/actions";

// const mapStateToProps = (state) => {
//   console.log(state);
//   return {
//     count: state.count,
//   };
// };

// const mapDispatchToProps = (dispatch) => {
//   return {
//     onADD() {
//       //   dispatch({ type: "ADD", data: 2 });
//       dispatch(Add(2));
//     },
//   };
// };

// const WithCounter = connect(mapStateToProps, mapDispatchToProps)(Counter);
const WithCounter = connect(
  (state) => ({ count: state.count }),
  // 底层封装,实际也调用了dispatch
  { Add, Less }
)(Counter);
export default WithCounter;

-展示组件Counter使用

import React, { Component } from "react";

export default class Counter extends Component {
  handleAdd = () => {
    // this.props.onADD();
    this.props.Add(2);
  };

  handleLess = () => {
    this.props.Less(1);
  };

  render() {
    console.log(this.props);
    return (
      <>
        <div>{this.props.count}</div>
        <button onClick={this.handleAdd}>type:"ADD"2</button>
        <button onClick={this.handleLess}>type:"Less"1</button>
      </>
    );
  }
}

react-redux完整概览

基础结构

在这里插入图片描述

container(容器组件)

withCounter.js

// 在Counter组件中,如果想用redux中的数据
// 1.先导入connect函数
import { connect } from "react-redux";

// 引入展示组件counter
import Counter from "../Counter";

// 导入action
import { Add, Less } from "../redux/actions";


const WithCounter = connect(
  (state) => ({ count: state.count }),
  { Add, Less }
)(Counter);
export default WithCounter;

redux

actions.js

// 将action对象封装起来  统称为actionCreator
// 引入常量
import { INCREMENT, DECREMENT } from "../redux/constants";

// 增加功能
function Add(data) {
  return {
    // type: "ADD",
    type: INCREMENT,
    data: data,
  };
}

// 减少功能
function Less(data) {
  return {
    type: DECREMENT,
    data: data,
  };
}

export { Add, Less };

constants.js

// 定义常量,方便后期统一维护管理

// 增加
export const INCREMENT = "INCREMENT";

// 减少
export const DECREMENT = "DECREMENT";

reducer.js

// 导入常量
import { INCREMENT, DECREMENT } from "../redux/constants";

export default function reducer(
  state = {
    count: 0,
    msg: "我爱你中国",
    arr: [1, 2, 3, 4],
  },
  action
) {
  switch (action.type) {
    // case "ADD":
    case INCREMENT:
      return {
        ...state,
        count: state.count + action.data,
      };
    case DECREMENT:
      return {
        ...state,
        count: state.count - action.data,
      };
    default:
      return state;
  }
}

store.js

import { createStore } from "redux";

import reducer from "./reducer"
const store = createStore(reducer);

export default store;

App.js

import React, { Component } from "react";

// 导入Provider
import { Provider } from "react-redux";
// 导入store
import store from "./redux/store";

// 最终用的是WithCounter
import WithCounter from "./container/WithCounter";

export default class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <div>
          <WithCounter></WithCounter>
        </div>
      </Provider>
    );
  }
}

Counter.js(展示组件)

import React, { Component } from "react";

export default class Counter extends Component {
  handleAdd = () => {
    this.props.Add(2);
  };

  handleLess = () => {
    this.props.Less(1);
  };

  render() {
    console.log(this.props);
    return (
      <>
        <div>{this.props.count}</div>
        <button onClick={this.handleAdd}>type:"ADD"2</button>
        <button onClick={this.handleLess}>type:"Less"1</button>
      </>
    );
  }
}

index.js

import React from "react";
import ReactDOM from "react-dom";

import App from "./App";

ReactDOM.render(<App />, document.getElementById("root"));

在这里插入图片描述

redux-thunk 使用

  • redux-thunk写异步 写在action中

1.yarn add redux-thunk

  • 安装yarn add redux-thunk
yarn add redux-thunk

2.导入thunk

  • 导入thunk import thunk from ‘redux-thunk’
import thunk from "redux-thunk"

3.导入 applyMiddleware函数

  • 导入redux中的一个函数:applyMiddleware
// 引入applyMiddleware
import { createStore ,applyMiddleware} from "redux";

4.将redux-thunk中间件,作为参数传递给 applyMiddleware

  • 将redux-thunk中间件,作为参数传递给 applyMiddleware
    == 在store中操作==
// 引入applyMiddleware
import { createStore ,applyMiddleware} from "redux";

// redux-thunk这个中间件,是专门用来帮助我们在redux中发送请求的
import thunk from "redux-thunk"
import reducer from "./reducer"
// 注意:所有的中间件都是需要在创建store的时候,传入到applyMiddleware这个函数里面.
// 如果有多个中间件applyMiddleware(thunk, 中间件,中间件)
// 中间件的执行顺序是按照书写顺序执行的
const store = createStore(reducer,applyMiddleware(thunk));

export default store;

5.将 middlewares 传递给 createStore

  • 将 middlewares 传递给 createStore,作为它的第三个参数

  • 注意:redux-thunk对 action 做了处理,异步操作就是放在action中被处理的!!!

// 同步的action 
const increment = () => {
   return { type: 'INCREMENT' }
}
//异步的action  --要求返回一个函数,这个函数可以拿到dispatch
const incrementAsync = () => {
    //thunk会处理这个函数,将dispatch传入到函数中
  return function(dispatch) {
    setTimeout(() => {
        dispatch({ type: 'INCREMENT' })
    }, 2000)
  } 
}

注意: 标准的异步请求应该有三个状态, 1.等待 2.成功 3.失败

异步需求完整版

  • 需求:点击按钮2s后加1

store 引入中间件

// 引入applyMiddleware
import { createStore ,applyMiddleware} from "redux";

// redux-thunk这个中间件,是专门用来帮助我们在redux中发送请求的
import thunk from "redux-thunk"
import reducer from "./reducer"
// 注意:所有的中间件都是需要在创建store的时候,传入到applyMiddleware这个函数里面.
// 如果有多个中间件applyMiddleware(thunk, 中间件,中间件)
// 中间件的执行顺序是按照书写顺序执行的
const store = createStore(reducer,applyMiddleware(thunk));

export default store;

action 定义异步功能

/* 
    需求1:数字增加1 {type:"ADD",data:1}
    需求2:数字增加2 {type:"ADD",data:2}
*/
// 将action对象封装起来  统称为actionCreator

// 引入常量
import { INCREMENT, DECREMENT, ASYNCADD } from "../redux/constants";

// 增加功能
function Add(data) {
  return {
    // type: "ADD",
    type: INCREMENT,
    data: data,
  };
}

// 减少功能
function Less(data) {
  return {
    type: DECREMENT,
    data: data,
  };
}

// 定义一个异步action
function asyncAdd(data){
  // 返回的是一个函数,这个函数可以接收到一个dispatch,可以理解为redux中的dispatch
  return dispatch => {
    // 执行异步操作
    setTimeout(() => {
      // 这里表示异步操作成功了
      dispatch(Add(data))
    }, 2000);
  }
}

export { Add, Less, asyncAdd };

withCounter 容器组件

// 在Counter组件中,如果想用redux中的数据
// 1.先导入connect函数
import { connect } from "react-redux";

// 引入展示组件counter
import Counter from "../Counter";

// 导入action
import { Add, Less, asyncAdd } from "../redux/actions";

const WithCounter = connect(
  (state) => ({ count: state.count }),
  // 底层封装,实际也调用了dispatch
  { Add, Less, asyncAdd }
)(Counter);
export default WithCounter;

counter 展示组件

import React, { Component } from "react";

export default class Counter extends Component {
  handleAdd = () => {
    // this.props.onADD();
    this.props.Add(2);
  };

  handleLess = () => {
     // 这个dec没有异步操作.调用了这个函数,这个函数中,调用了dispatch,所以reducer执行了
    // 相当于: 调用这个函数之后,reducer直接执行了
    this.props.Less(1);
  };

  handleAsync = () => {
     // 这个asyncInc是一个异步anction. 调用这个函数的时候,先执行了异步action中返回的那个函数 , 这个函数执行的时候,去执行了异步请求,异步请求成功,才调用dispatch.调用dispatch.reducer才执行
    this.props.asyncAdd(1);
  };

  render() {
    console.log(this.props);
    return (
      <>
        <div>{this.props.count}</div>
        <button onClick={this.handleAdd}>type:"ADD"2</button>
        <button onClick={this.handleLess}>type:"Less"1</button>
        <button onClick={this.handleAsync}>asyncAdd 减1</button>
      </>
    );
  }
}

其它参考上面react-redux

chrome的redux插件

在这里插入图片描述

单独使用redux浏览器插件

  • 在store中 createStore(),第二个参数传入
    在这里插入图片描述

window.REDUX_DEVTOOLS_EXTENSION && window.REDUX_DEVTOOLS_EXTENSION()

// 1.单独使用redux浏览器插件
const store = createStore(
  reducer,
  // 单独使用redux浏览器插件
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

在这里插入图片描述

和中间件配合使用

// 下载包
yarn add redux-devtools-extension

// 导入
import { composeWithDevTools } from "redux-devtools-extension";

// 使用
const store = createStore(users, composeWithDevTools(applyMiddleware(thunk)));

在这里插入图片描述
在这里插入图片描述

combineReducers

  • redux 中提供的一个 API
  • 作用:
    • 1 用来将多个 reducer 合并为一个 根reducer
    • 2 会影响 redux 中的状态值
  • 有了这个方法之后,将来 redux 中就可以有任意多个 reducer,这样,每个 reducer 只需要处理某个特定的状态即可。
  • 注意:每个 reducer 中的状态最终被全部合并到一个对象中。对象中的键就是参数对象的键

引入combineReducers

import { createStore, combineReducers} from 'redux'
const rootReducer = combineReducers({
  todos: reducer,
  filter:filter
})

const store = createStore( rootReducer )

store.getState() // 初始状态: { todos: [], filter: 'all' }
// 此时的应用的状态为:{ todos: [], filter: 'all' }
const rootReducer = combineReducers({
  todos: reducer,
  filter
})

// 该写法等价于上述combineReducers调用:
function rootReducer(state = {}, action) {
  return {
    todos: reducer(state.todos, action),
    filter: filter(state.filter, action)
  }
}

// 当我们使用 dispatch( 动作 ) 分发了一个动作的时候, redux 中所有的 reducer 全部都会执行一次
// 因为 redux 无法知道到底是哪个reducer来处理该状态,所以,所有的 reducer 全部都会被重新执行一次

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值