Redux是一款状态管理库,并且提供了react-redux库来与React亲密配合, 但是总是傻傻分不清楚这2者提供的API和相应的关系。这篇文章就来理一理。

Redux

Redux 三大核心

Redux的核心由三部分组成:Store, Action, Reducer

  • Store : 是个对象,贯穿你整个应用的数据都应该存储在这里。
  • Action: 是个对象,必须包含type这个属性,reducer将根据这个属性值来对store进行相应的处理。除此之外的属性,就是进行这个操作需要的数据。
  • Reducer: 是个函数。接受两个参数:要修改的数据(state) 和 action对象。根据action.type来决定采用的操作,对state进行修改,最后返回新的state

===== Store =====
{
todos: [],
visibilityFilter: 'SHOW_ALL'
} ===== Action =====
{
type: 'ADD_TODO',
text: 'Build my first Redux app'
} ===== Reducer =====
const todos = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
{
id: action.id,
text: action.text,
completed: false
}
]
default:
return state
}
}

Redux核心之间的关系

在上一部分,我们提到了,我们触发actionreducer来处理。这就是二者之间的关系。那么我们怎么触发action呢?Store这个对象提供了dispatch方法触发actiondispatch方法接受action对象作为参数。因此,我们可以了解三者之间的关系:


`store` ➡️ `dispatch` ➡️ `action` ⬅️ `reducer`

Store

我们通过redux提供的createStore这个方法来创建一个Store。它接受对store进行处理的reducer作为参数。

Store有三个方法:

  • getState:用来获取store里面存储的数据。
  • dispatch: store里的数据不能直接修改,只能通过触发action来进行修改,这个方法就是用来触发action
  • subscibe:订阅store改变时,要进行的操作。比如在react中,当store改变时,我们需要调用render方法对视图进行更新。

const store = createStore(reducer); store.getState(); // { todos: [], visibilityFilter: 'SHOW_ALL' } store.dispatch({
type: 'ADD_TODO',
text: 'Build my first Redux app'
}); store.subscibe(() => {
console.log(store.getState());
});

Reducer

我们可以将对store的操作,写在一个reducer中,比如:


function todoApp(state = initialState, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return Object.assign({}, state, {
visibilityFilter: action.filter
})
case ADD_TODO:
case TOGGLE_TODO:
return Object.assign({}, state, {
todos: todos(state.todos, action)
})
default:
return state
}
}

可以看到这个reducerstorevisibilityFiltertodos的两部分数据进行了处理。随着应用的复杂,如果我们把对所有数据的处理,都写在一个reducer中,那么它会变得很冗杂。如果我们将对每一部分的数据的处理,写在一个单独的reducer中,它接受该部分的数据作为state。那么整个reducer会变得整洁和清晰。

因此,redux为我们提供了combineReducer这个API,帮助我们分开书写reducer, 并且最终把这些reducer给集合到一个根reducer中。


// 对todos进行处理
function todos(state = [], action) {
switch (action.type) {
case ADD_TODO:
return [
...state,
{
text: action.text,
completed: false
}
]
default:
return state
}
} // 对 visibilityFilter 进行处理
function visibilityFilter(state = SHOW_ALL, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return action.filter
default:
return state
}
} // 生成 root reducer
function todoApp(state = {}, action) {
return {
visibilityFilter: visibilityFilter(state.visibilityFilter, action),
todos: todos(state.todos, action)
}
} // 创建store
const store = createStore(todoApp)

react-redux

上一部分我们介绍了redux的核心。可以看到,redux是独立的应用状态管理工具。它是可以独立于react之外的。如果我们需要在react当中运用它,那么我们需要手动订阅store的状态变化,来对我们的react组件进行更新。那么react-reudx这个工具,就帮我们实现了这个功能,我们只需对store进行处理,react组件就会有相应的变化。

这个工具主要提供两个API

connect

现在我们有了store,那么我们怎么才能在我们的组件中对它们进行操作呢?connect就为提供了这个功能。它接受mapStateToProps, mapDispatchToProps等作为参数。比如在我的TodoList这个组件中需要用到todos这部分数据,那么我完善mapStateToProps这个函数,它接受store中的state作为参数,返回一个对象,属性就是state中我们需要的数据:


const mapStateToProps = state => {
return {
todos: state.todos
}
}

mapStateToProps就将我们的state转换为了props对象。

同样的,我们可能需要在组件中对state进行处理。mapDispatchToProps就是帮助我们在组件中通过props调用dispatch来触发action的:


const mapDispatchToProps = dispatch => {
return {
onTodoClick: id => {
dispatch(toggleTodo(id))
}
}
}

最后我们调用connect这个方法,将mapStateToPropsmapDispatchToProps生成的props注入到需要使用它的组`中:


const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)

这样,我们在TodoList这个组件中,就能直接通过props.todos获取到todos中的数据, 通过props.onTodoClicktodos进行处理。

provider

上面我们调用connect时,在mapStateToPropsmapDispatchToProps我们分别用到了storestatedispatch。但是在组件中的store是哪里凭空冒出来的呢?

provider就是来解决这个事的。Provider使它的子孙在调用connect方法时,都能获取到store


const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList) const App = () => (
<div>
<AddTodo />
<VisibleTodoList />
<Footer />
</div>
) <Provider store={store}>
<App />
</Provider>

这样,Provider的子孙组件都能在调用connect时获取到store

总结

  • Redux: store, action, reducer

    • store: getState, dispatch, subscribe
    • combineReducers
    • createStore
    • store ➡️ dispatch ➡️ action ⬅️ reducer
  • react-redux:

    • connect: 将store作为props注入
    • Provider: 使store在子孙组件的connect中能够获取到。

来源:https://segmentfault.com/a/1190000011473973

Redux 关系图解的更多相关文章

  1. CGI、FastCGI和PHP-FPM关系图解

    CGI.FastCGI和PHP-FPM关系图解   webapp即是php解析器等 当Web Server收到 index.php 这个请求后,会启动对应的 CGI 程序,这里就是PHP的解析器.接下 ...

  2. 简单实用UML关系图解

    一句话UML,再记不住就要DPP了: 关系 图解 代码 备注 1:继承关系(Generalization)     2:实现关系(Realization)     3:依赖关系(Dependency) ...

  3. [转帖]UML类图关系图解

    UML类图关系图解 https://www.cnblogs.com/TvvT-kevin/p/9357339.html 一.类结构 在类的UML图中,使用长方形描述一个类的主要构成,长方形垂直地分为三 ...

  4. 前端(十一):props、state及redux关系梳理

    所谓状态机,是一种抽象的数据模型,是“事物发展的趋势”,其原理是事件驱动.广泛地讲,世界万物都是状态机. 一.状态机是一种抽象的数据模型 在react中,props和state都可以用来传递数据.这里 ...

  5. UML中关系图解

    转自http://blog.csdn.net/duran1986/article/details/5573415 最近在教软件工程项目实践,就又仔细了解了下UML中各种关系的意义,虽然有点简单,但是有 ...

  6. UML类图中类与类的四种关系图解

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  7. UML类图关系图解

    一.类结构 在类的UML图中,使用长方形描述一个类的主要构成,长方形垂直地分为三层,以此放置类的名称.属性和方法. 其中, 一般类的类名用正常字体粗体表示,如上图:抽象类名用斜体字粗体,如User:接 ...

  8. mount过程分析之六——挂载关系(图解)【转】

    转自:https://blog.csdn.net/zr_lang/article/details/40343899 引言 写到这里我们已经从mount文件系统调用的入口开始,分析到内核的mount,通 ...

  9. MVC与MVVM关系图解

随机推荐

  1. 在线PDF的实现 纯js

    /// <summary> /// 使用微软的TransmitFile下载文件 /// </summary> /// <param name="filePath ...

  2. ef复杂模型添加

    模型浏览器 函数导入-添加存储过程名称 添加复杂实体.复杂实体可以手动在xml里面创建.在complextype里面

  3. C++STL中的unique函数

    头文件:#include<iostream> 函数原型:iterator unique(iterator it_1,iterator it_2); 作用:元素去重,即”删除”序列中所有相邻 ...

  4. 185.[USACO Oct08] 挖水井 (第三次考试大整理)

    185. [USACO Oct08] 挖水井 输入文件:water.in   输出文件:water.out   简单对比 时间限制:1 s   内存限制:128 MB 农夫约翰决定给他的N(1< ...

  5. JedisCluster和springboot整合

    maven依赖 springboot整合jedisCluster相当简单,maven依赖如下: <dependency> <groupId>org.springframewor ...

  6. Module not found: Error: Can't resolve ' vue-resource'

    问题: 在学习vue的过程中出现了这个问题,说明VueResource模块没有安装. 解决方法: 打开终端,进入当前项目所在目录,输入指令 npm install vue-resource --sav ...

  7. Access to the requested object is only available from the local network phpmyadmin

    http://stackoverflow.com/questions/11999371/access-to-the-requested-object-is-only-available-from-th ...

  8. linux xz压缩解压

    1. 解压 xz 格式文件 方法一: 需要用到两步命令,首先利用 xz-utils 的 xz 命令将 linux-3.12.tar.xz 解压为 linux-3.12.tar,其次用 tar 命令将 ...

  9. Masonry 布局 scrollView

    原理 scrollView的高度(纵向滑动时)时靠内部的子控件撑起来的.我们直接给ScrollView布局会发现失败.用层级检查器发现,ScrollVIiw的高度有问题,我们可以选择添加一个UIVie ...

  10. $_SERVER 中HTTP_HOST 和 SERVER_NAME

    本来打算获取当前页面的url的   拼接时发现 $_SERVER['SERVER_NAME'] 并不是当前的url链接 打印整个$_SERVER  发现 [SERVER_NAME] => lvs ...