redux
起源
2014年 Facebook 提出了 Flux 架构的概念,采用 单向数据流 思想。
2015年,Redux 出现,将 Flux 与 函数式编程 结合一起,很短时间内就成为了最热门的状态管理架构。
Redux 概述
yarn add redux
Redux 是 JavaScript 应用的可预测状态容器,用来集中管理状态。
特点:集中管理、可预测、易于测试、易于调试、强大的中间件机制满足你所有需求。
注意:redux 是一个独立于 react 的库,可以配合任何 UI 库/框架来使用。
redux的三大原则
单一数据源
State是只读的
使用纯函数来执行修改
什么情况下需要使用redux
-
总体原则: 大型项目状态管理复杂才用
-
某个组件的状态,需要共享
-
某个状态需要在任何地方都可以拿到
-
一个组件需要改变全局状态
-
一个组件需要改变另一个组件的状态
三个核心概念
计数器案例:点击 +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 全部都会被重新执行一次