Redux及React-Redux概述
Posted 橘猫吃不胖~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redux及React-Redux概述相关的知识,希望对你有一定的参考价值。
React Redux概述
Redux概述
1 设计思想
Redux是javascript的状态管理器。可以和React配合,也可以和Vue配合。
- Redux将应用中的所有状态存储在store中(store是全局的),里面存在一个状态树state tree。
- store本身不能修改自己,它通过store.dispatch派发相应的行为(action)给用户定义的reducer函数,来生成新的store(更新store)
- 其他组件通过订阅store中的state来刷新自己的视图
- 强调:Redux设计是基于“发布——订阅”模式
2 三大原则
- 整个应用有且只有一个store
- state是只读的,修改state只能通过派发action来实现(将action派发给reducer纯函数1来实现)。因此开发时第一步是编写reducer函数。
- 单一数据源2的设计便于状态(数据)的统一管理,便于react组件之间的数据传递
缺点:
(1)需要手动引入store,不方便
(2)需要手动订阅,不方便
3 使用方法
1、安装模块:安装redux
npm install redux
2、通过createStore生成store:Redux 提供createStore这个函数,用来生成 Store。
import createStore from "react";
function reducer()
let store = createStore(reducer);
注意:
(1)reducer是一个纯函数,由用户定义
(2)其返回值是一个store对象,该对象有以下方法可调用:
方法 | 含义 |
---|---|
store.getState() | 获取状态 |
store.dispatch() | 派发action |
store.subscribe() | 订阅store中state的变化 |
3、定义reducer函数
reducer是一个纯函数,由用户定义,它的返回值取决于参数。
它需要两个参数,分别是state和action,state是旧的状态,不可直接修改,而是需要根据action.type不同,来生成新的state并返回。
4、更新state
通过store.dispatch()来派送不同的action,在reducer中通过action.type来判断action的类型,根据类型执行不同的更新操作。
5、订阅store中的state
this.unSubscribe = store.subscribe(() =>
// 获取新的state
)
强调:store.subscribe()函数的返回值为函数,用于取消订阅
注:没有派送任何action时,也会有一个action的原因:store为了拿到初始值,会自动派发一个action
手撕代码:手写实现createStore函数功能的代码
function myCreateStore(reducer)
let state;
const listeners = [];
// 返回最新的state
function getState()
return state;
// 派发action
function dispatch(action)
state = reducer(state, action);
listeners.forEach(listener => listener());
// 订阅:返回取消订阅函数
function subscribe(listener)
listeners.push(listener);
return function ()
const index = listeners.indexOf(listener);
listeners.splice(index, 1);
// 获取state默认值
dispatch(type: "橘猫吃不胖---@@redux/INTTg.u.b.z.n.n");
// 返回store,一个对象
return
getState,
dispatch,
subscribe
export default myCreateStore;
4 bindActionCreators
redux 提供了 bindActionCreators 功能,将action的函数与store.dispatch进行绑定。绑定后就不用store.dispatch直接派发action。
用法:
let/const 变量名 = bindActionCreators(action函数名,store.dispatch)
5 【案例】实现计数器
1、效果展示:
2、编写store.js文件。在该文件中实现了生成State、创建store和生成reducer函数。
import createStore from "redux"; // 生成Store
// 定义常量
export const ADD = "ADD";
export const MINUS = "MINUS";
// 创建reducer函数,接收两个参数
// state:旧的状态,不可以直接修改,而是根据action.type的不同生成新的state并返回
// action:不同的动作,在本例中指ADD和MINUS
function reducer(state = count: 0, action)
// 首次加载后,即使没有action,控制台也输出了该信息
// 这时因为store为了拿到state的初始值count:0,会自动派发一次actiontype: "@@redux/INIT1.s.m.m.c.n"
// Redux内部使用“发布——订阅”模式
console.log(action);
// 对action进行判断
switch (action.type)
case ADD:
return count: state.count + 1;
break;
case MINUS:
return count: state.count - 1;
break;
default:
return state;
// 创建store对象
let store = createStore(reducer);
export default store; // 导出
3、编写Counter.js文件,在该文件中实现了页面的效果,在这里有3中写法:
(1)普通方法实现
import React from "react";
// 导入store对象,通过该对象派发action
import store from "../redex/store";
// 导入actions
import bindActions from "../redex/actions";
// 创建类组件,实现页面效果
class Counter extends React.Component
constructor(props)
super(props);
this.state =
// 将store中的最新的state赋给当前组件的state
// getState():获取最新的state tree
// count是在store.js文件中定义的,初始值为0
number: store.getState().count,
componentDidMount() // 页面加载完成后执行该函数
// 对store的state进行订阅
// store.subscribe可以实现订阅,同时该方法会返回一个函数,用于取消订阅
// 设置this.unSubScribe为当前类的属性,表示可以取消订阅的对象
this.unSubScribe = store.subscribe(() =>
this.setState(
number: store.getState().count
)
)
componentWillUnmount()
// 在组件卸载时取消订阅
this.unSubScribe();
render()
return (
<div>
/*页面上显示当前状态下的数值*/
<p>this.state.number</p>
/*当点击“加1”按钮时派发行为action:ADD*/
<button onClick=() => store.dispatch(type: "ADD")>加1</button>
<button onClick=() => store.dispatch(type: "MINUS")>减1</button>
</div>
);
export default Counter;
(2)使用bindActionCreators实现:
import React from "react";
// 导入store对象,通过该对象派发action
import store from "../redex/store";
import bindActionCreators from "redux";
// 导入actions
import bindActions from "../redex/actions";
//定义action函数
function add()
return type: "ADD"
function minus()
return type: "MINUS"
//进行绑定
const bindAdd = bindActionCreators(add, store.dispatch);
const bindMinus = bindActionCreators(minus, store.dispatch);
// 创建类组件,实现页面效果
class Counter extends React.Component
constructor(props)
super(props);
this.state =
// 将store中的最新的state赋给当前组件的state
// getState():获取最新的state tree
// count是在store.js文件中定义的,初始值为0
number: store.getState().count,
componentDidMount() // 页面加载完成后执行该函数
// 对store的state进行订阅
// store.subscribe可以实现订阅,同时该方法会返回一个函数,用于取消订阅
// 设置this.unSubScribe为当前类的属性,表示可以取消订阅的对象
this.unSubScribe = store.subscribe(() =>
this.setState(
number: store.getState().count
)
)
componentWillUnmount()
// 在组件卸载时取消订阅
this.unSubScribe();
render()
return (
<div>
/*页面上显示当前状态下的数值*/
<p>this.state.number</p>
<button onClick=bindAdd>加1</button>
<button onClick=bindMinus>减1</button>
</div>
);
export default Counter;
(3)将bindActionCreators抽离到单独的文件actions实现,这样可以使代码的结构清晰,因此actions.js代码如下:
import bindActionCreators from "redux";
import store from "./store";
//定义action函数
function add()
return type: "ADD"
function minus()
return type: "MINUS"
const actions = add, minus;
const bindActions = bindActionCreators(actions, store.dispatch);
export default bindActions;
Counter.js文件代码如下:
import React from "react";
// 导入store对象,通过该对象派发action
import store from "../redex/store";
// 导入actions
import bindActions from "../redex/actions";
// 创建类组件,实现页面效果
class Counter extends React.Component
constructor(props)
super(props);
this.state =
// 将store中的最新的state赋给当前组件的state
// getState():获取最新的state tree
// count是在store.js文件中定义的,初始值为0
number: store.getState().count,
componentDidMount() // 页面加载完成后执行该函数
// 对store的state进行订阅
// store.subscribe可以实现订阅,同时该方法会返回一个函数,用于取消订阅
// 设置this.unSubScribe为当前类的属性,表示可以取消订阅的对象
this.unSubScribe = store.subscribe(() =>
this.setState(
number: store.getState().count
)
)
componentWillUnmount()
// 在组件卸载时取消订阅
this.unSubScribe();
render()
return (
<div>
/*页面上显示当前状态下的数值*/
<p>this.state.number</p>
<button onClick=bindActions.add>加1</button>
<button onClick=bindActions.minus>减1</button>
</div>
);
export default Counter;
最后在App.js文件中使用<Counter/>
组件就可以看到效果。
React-Redux概述
1 简介
(1)是redux官方给出的react绑定库
(2)不是react内置的,使用时需要安装
(3)通常和redux结合使用
(4)方便react组件读取store中的数据,并且向store中分发action来更新数据
2 使用过程
1、安装
npm install redux
npm install react-redux
2、Provider和connect
(1)Provider:将store传递给所有的子组件
<Provider store=用户定义的store>
<App/>
</Provider>
(2)connect:高阶组件(传入一个组件,它会返回新的加工后的组件)
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
[mapStateToProps]:函数,用于监控Redux store的变化,一旦store的值发生改变,该函数就会被调用,将redux store的state合并到组件的props中
[mapDispatchToProps]:将action合并到组件的props中
[mergeProps], [options]参数可以不写,用默认值即可
示例代码:
connect(mapStateToProps,mapDispatchToProps)(组件名)
含义:将store中的state和store派发的action都合并到给定组件的props属性中
3 【案例】实现计数器
1、效果展示
2、编写store.js文件,在该文件中定义了reducer函数,生成了store,代码如下:
import createStore from "redux";
export const ADD = "ADD";
export const MINUS = "MINUS";
function reducer(state = count: 0, action)
switch (action.type)
case ADD:
return count: state.count + 1
case MINUS:
return count: state.count - 1
default:
return state;
let store = createStore(reducer);
export default store;
3、编写action.js文件,在该文件中定义了两个函数,返回了action.type,代码如下:
function add()
return type: "ADD";
function minus()
return type: "MINUS"
const actions = add, minus;
export default actions;
4、编写counter.js文件,在该文件中实现了效果,代码如下:
import React from "react";
import connect from "react-redux";
import actions from "../actions/action";
class Counter extends React.Component
render()
return (
<>
<p>Count:this.props.count</p>
<br/>
<button onClick=this.props.add>Count++</button>
<button onClick=this.props.minus>Count--</button>
</>
);
const mapStateToProps = (state) => state; // 函数,监视store中的state的变化
const mapDispatchToProps = //对象:保存的action
...actions
// 将store中的state和需要store派发的action绑定到组件中
export default connect(mapStateToProps, mapDispatchToProps)(Counter);
5、修改App.js中代码,具体如下:
import './App.css';
import Counter from "./components/counter";
function App()
return (
<div className="App">
<header className="App-header">
<Counter/>
</header>
</div>
);
export default App;
6、修改index.js文件代码如下:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import Provider from "react-redux";
import store from "./react-redux/store";
ReactDOM.render(
<Provider store=store>
<App/>
</Provider>,
document.getElementById('root')
);
以上是关于Redux及React-Redux概述的主要内容,如果未能解决你的问题,请参考以下文章
从 react-redux 迁移到 redux-toolkit 后使用 configureStore 传递初始状态的最佳方法