React 初探(五)- Redux、React-Redux

概述

之前写了一些 Redux 的一些示例,这次主要是跟着 Redux 官方网站 中的示例继续探索 Redux

Counter Vanilla

demo 代码在线运行, demo 仅仅使用了 Redux 和原生 JS。当点击按钮时:

  1. store dispatch 一个 action === 触发一个事件 === 派发一个动作
  2. 根据操作生成新的 state + 触发一个事件
  3. store 接收到事件,重新 render

将上述 demo 完善在线运行
注意: 当有异步操作时,store.dispatch 要在异步之后在去 store.dispatch

React + Redux 示例

这里需要先安装 create-react-app

npm i -g create-react-app

在安全的目录下运行:

create-react-app react-redux-demo

创建完成之后,会有一个提示

begin

之后进入 react-redux-demo 目录下再安装 Redux

// 如果没有 yarn 可以先安装一下
// npm i -g yarn
yarn add redux

之后运行

yarn start

它会默认开一个 3000 端口的本地服务。之后将之前的 Counter Vanilla demo 代码迁移到这个目录下。可以 clone 到本地

git clone https://github.com/bowen-wu/react-first-exploration.git
git checkout d2f85f97a627d374185f01f9cdd7408327c4982a
cd react-redux-example
yarn install
yarn start

之后便在本地运行了,将 Vanilla 升级为 React 之后可以看到:当更新的时候,React + Redux 仅仅会更新该更新的地方,而 Vanilla 会更新整个 App。React 会根据 DOM diff 找到该更新的地方进行局部更新。

但是现在更新 store 的时候有两种方式:

  1. index.js 文件将更新 store 的方法传给子代,之后子代调用这个方法,从而更新 store
  2. store 传递下去,之后子代自己 store.dispatch
    index.js

    App.js

但是两种方法一种是更新 store 时,逐层调用父组件的方法,一种是将 store 逐层传递下去一种是一层一层的往上调用,一种是一层一层的往下传

React-Redux

那么如何解决上述问题,这时可以借助 React-Redux 来解决上述问题。React-Redux 官网。React-Redux 可以让你的 React 组件从 Redux store 中读取数据,并且 dispatch actions 从而更新数据。

React Redux is the official React binding for Redux. It lets your React components read data from a Redux store, and dispatch actions to the store to update data

  1. 需要安装 React-Redux
npm install --save react-redux

或者

yarn add react-redux
  1. 借助 React-Redux 实现上述功能,主要是修改 index.jsApp.js 文件,修改的 diff,最终呈现 index.js 文件App.js 文件

  2. React-Redux 的相关 Api,它有三个 Api,分别是 ProviderconnectconnectAdvanced ,其中常用的便是 Providerconnect,之后看一下关于 Providerconnect官方实例

Provider

makes the Redux store available to the rest of your app


Provider 示例

connect

React Redux provides a connect function for you to connect your component to the store。connect 接收四个不同的参数,分别为 mapStateToPropsmapDispatchToPropsmergePropsoptions

connect 示例

  • connect 的调用方式为 connect(mapStateToProps, mapDispatchToProps)(component)。这种调用方式原理即 return 一个函数
    connect 调用方式
  • mapStateToProps: Function -> (state, ownProps?) => Object -> subscribe Redux store 更新,只要 store 更新,则 mapStateToProps 将会被调用,return Object,这个对象将会合并到组件的 props 中,如果不想 subscribe store 更新,可以写 null | undefined
    • state -> mapStateToProps 第一个参数 -> 当 store 更新时,mapStateToProps 函数将会被调用,并且传递一个参数 store
    • ownProps -> 如果 mapStateToProps 提供了两个参数,那么当 store 更新时或者组件接收到新的 props 的时候将会被调用,组件的 props 作为第二个参数
  • mapDispatchToProps: Function | Object -> Object | (dispatch, ownProps?) => Object -> 如果定义了函数 mapDispatchToProps,它将带着最多两个参数被调用,返回一个对象,它也会被合并到 props 中,用来生成 action 相关操作
    • dispatch: Function -> 如果 mapDispatchToProps 别声明为一个带有一个参数的函数,它将被 dispatch 你的 store

偏函数

connect()() 这种能接收两次参数的函数,把 connect() 叫做偏函数

视图更新过程

当点击 +1 按钮时:

  1. 调用 this.add1.bind(this)
  2. 调用 this.props.add1();,其中 this.props.add1 是根据 connect 第二个参数而来,即
    connect 第二个参数
  3. 调用 mapDispatchToProps 中的 add1,将会 dispatch 一个 action
  4. 之后 index.js 文件中的 reducer 接收到 action,执行函数,并且 return 新的 state
    reducer 函数
  5. Provider 接收到 store 的更新,之后告知所有具有 mapStateToProps 参数的 connect,并且 mapStateToProps 将会被调用,并且接受新的 store
  6. 页面中如果发现有需要被更新的数据,将会重新渲染( 更新 )

总结

Vanilla.js

  1. 引入 Redux
  2. 生成 store,其中 stateChanger 是所有状态变更的过程,即根据 action type 返回新的 state
    let store = Redux.createStore(stateChanger)
    
  3. store 放在 render 中,render 一下,之后得到了第一次界面
    render(store);
    
  4. 当点击 +1 按钮时,就会触发一个 action,之后就会进入状态变更的逻辑,并且产生一个新的 state
  5. 新的 state 将会导致 render 再次运行,之后会获取最新的 state,页面重新渲染数据

React + Redux

与 Vanilla.js 变化在于将 Vanilla.js 变为 React,其他都没有改变。

  • 优点:当点击按钮时,只有该更新的地方更新,其他不需要更新的地方将会不更新。
  1. 第一次 render 时获取到数据,并且将数据传给 AppApp 得到数据后,将数据渲染到页面中
  2. 当点击 +2 按钮时,将会执行父组件的 onAdd2,父组件的 onAdd2 将会 dispatch 一个 action
  3. 之后就会进入状态变更的逻辑,并且产生一个新的 state
  4. 之后将会执行 render

React-Redux

与 React + Redux 区别:

  1. 状态变更时添加一个变量 n,方便后面使用
  2. 没有将 store 传给 App, 而是传给了 Provider优点Provider 会把 store 传给每一个它里面的组件
  3. App 通过 connect 获取 storeconnect 里面将会有获取 statedispatch 一个 action 的相关操作,即 mapStateToProps ( 映射 state 到 props ) 和 mapDispatchToProps ( 映射 dispatch 到 props )
  4. 产生新的 state 之后不会执行 render,而是通过 Provider 告诉所有组件是否需要更新,如果需要更新将会重新渲染
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容