关于props和state以及redux中的state
React的数据模型分为共有数据和私有数据,共有数据可以在组件间进行传递,私有数据为当前组件私有。共有数据在React中使用props对象来调用,它包含标签所有的属性名称和属性值,props对象有三个特性,单向流动性、显示传递性和只读性。单向流动性是指React的数据只能由父组件传递到子组件,而不能由子组件传递到父组件;显示传递性是指必须明确地在子组件中通过属性赋值,数据才可以传递到子组件;只读性是指props数据是只读的,数据修改后并未改变原始的数据模型,而是会新生成一份数据模型,并将新的数据模型加载到原始父元素,从而完成数据的传递和组件状态的更改。私有数据为组件私有,在React使用state对象来调用,state数据模型可以方便地进行更新操作,并且不会影响到其他组件。
需要理解的是,props是一个父组件传递给子组件的数据流,这个数据流可以一直传递到子孙组件。而state代表的是一个组件内部自身的状态(可以是父组件、子孙组件)。改变一个组件自身状态,从语义上来说,就是这个组件内部已经发生变化,有可能需要对此组件以及组件所包含的子孙组件进行重渲染。而props是父组件传递的参数,可以被用于显示内容,或者用于此组件自身状态的设置(部分props可以用来设置组件的state),不仅仅是组件内部state改变才会导致重渲染,父组件传递的props发生变化,也会执行。
既然两者的变化都有可能导致组件重渲染,所以只有理解props与state的意义,才能很好地决定到底什么时候用props或state。
下面说一下react-redux中是如何维护state的,react-redux提供两个关键模块:Provider和connect。
Provider
Provider这个模块是作为整个App的容器,在你原有的App Container的基础上再包上一层,它的工作很简单,就是接受Redux的store作为props,并将其声明为context的属性之一,子组件可以在声明了contextTypes
之后可以方便的通过this.context.store
访问到store。不过我们的组件通常不需要这么做,将store放在context里,是为了给下面的connect用的。
这个是Provider的使用示例:
// config app root
const history = createHistory()
const root = (
<Provider store={store} key="provider">
<Router history={history} routes={routes} />
</Provider>
) // render
ReactDOM.render(
root,
document.getElementById('root')
)
connect
这个模块是算是真正意义上连接了Redux和React,正好它的名字也叫connect。
Redux是怎么运作的?
首先store中维护了一个state,我们dispatch一个action,接下来reducer根据这个action更新state。映射到我们的React应用中,store中维护的state就是我们的app state,一个React组件作为View层,做两件事:render和响应用户操作。于是connect就是将store中的必要数据作为props传递给React组件来render,并包装action creator用于在响应用户操作时dispatch一个action。
然后几个问题:
- React组件如何响应store的变化?
- 为什么connect选择性的merge一些props,而不是直接将整个state传入?
Connect的组件,它在包装原有组件的基础上,还在内部监听了Redux的store的变化。
但是通常,我们connect的是某个Container组件,它并不承载所有App state,然而我们的handler是响应所有state变化的,于是我们需要优化的是:当storeState变化的时候,仅在我们真正依赖那部分state变化时,才重新render相应的React组件,那么什么是我们真正依赖的部分?就是通过mapStateToProps
和mapDispatchToProps
得到的。具体优化的方式就是在shouldComponentUpdate
中做检查,如果只有在组件自身的props改变,或者mapStateToProps
的结果改变,或者是mapDispatchToProps
的结果改变时shouldComponentUpdate
才会返回true,检查的方式是进行shallowEqual的比较。
关于connect的使用:
Then, we wrap the components we want to connect to Redux with connect() function from react-redux. Try to only do this for a top-level component, or route handlers. While technically you can connect() any component in your app to Redux store, avoid doing this too deeply because it will make the data flow harder to trace.
Deep prop chains was one of the issues with React that led me to use Flux; the tradeoff for making it easier to trace the data flow is that you need to setup/maintain/trace the prop flow, and more importantly, parents need to know about the data requirements of their children.
redux的作者说从技术上虽然允许连接任意组件,但是避免过多使用,否则数据流会很难追踪,尽量只连接根组件,有开发者评论说redux如果只连接根组件,子组件嵌套过多,prop也会一级一级传递,很繁琐,这应该也是redux一直被诟病的一点。
结语:所以redux中的state和组件自身维护的state并不是一个东西,每个组件本身有自己的state,但在Redux中,应用的状态是全部存在一个单一的树结构中的,换句话说,应用的所有状态信息都存储在这个包含map和array的数据结构中。一个Redux应用的状态树是不可变的数据结构。这意味着,一旦你得到了一棵状态树,它就不会在改变了。任何用户行为改变应用状态,你都会获取一棵映射应用改变后新状态的完整状态树。这说明任何连续的状态(改变前后)都被分别存储在独立的两棵树。你通过调用一个函数来从一种状态转入下一个状态。
关于props和state以及redux中的state的更多相关文章
- React修改state(非redux)中数组和对象里边的某一个属性的值
在使用React时,会经常需要处理state里边设置的初始值以达到我们的实际需求,比如从接口获取到列表数据后要赋值给定义的列表初始值,然后数据驱动view视图进而呈现在我们眼前,这种最简单的赋值方式实 ...
- 如何优雅的设计Redux中的Store
用了几个月的redux,现在回过来总结一下. 刚开始用的时候遇到一个比较大的疑问,就是如何设计redux的store中的state树,这应该是我在使用redux中最大的一个疑问,阻挡了我前进的脚步,当 ...
- 前端(十一):props、state及redux关系梳理
所谓状态机,是一种抽象的数据模型,是“事物发展的趋势”,其原理是事件驱动.广泛地讲,世界万物都是状态机. 一.状态机是一种抽象的数据模型 在react中,props和state都可以用来传递数据.这里 ...
- React中的state与props的再理解
props可以看做是 property 的缩写的复数,可以翻译为属性,类似于HTML 标签的自定义属性.在大多数React教程里讲 state 和 props 主要的区别在于 props 是不可变的, ...
- React中的State与Props
一.State 1.什么是 state 一个组件的显示形态可以由数据状态和外部参数决定,其中,数据状态为 state,外部参数为 props 2.state 的使用 组件初始化时,通过 this.st ...
- 通过三张图了解Redux中的重要概念
上周利用业余的时间看了看Redux,刚开始有点不适应,一下在有了Action.Reducer.Store和Middleware这么多新的概念. 经过一些了解之后,发现Redux的单向数据里的模式还是比 ...
- Redux中的重要概念
Action/Reducer/Store 首先,先看看第一张图,图中展示了Redux的单向数据流,以及Action.Reducer和Store这三个核心概念. 下面就围绕上图,非别介绍Action.R ...
- react-native中的state
我们使用两种数据来控制一个组件:props和state.props是在父组件中指定, 而且一经指定,在被指定的组件的生命周期中则不再改变. 对于需要改变的数据,我们需要使用state. 假如我们需要制 ...
- 25.redux回顾,redux中的action函数异步
回顾:Redux: 类似于 Vuex 概念:store/reducer/action action:动作 {type,.....} 一定要有type 其他属性不做限制 reducer:通过计算产生st ...
随机推荐
- HTML5它contenteditable属性
HTML5它contenteditable属性 1.功能说明 (1)功能:同意用户编辑元素中的内容 (2)说明:是一个布尔值.false是不能编辑,true为可编辑 2.分析实例 (1)content ...
- HDU 3094 A tree game 树删边游戏
叶节点SG值至0 非叶节点SG值至于它的所有子节点SG值添加1 XOR和后 #include <cstdio> #include <cstring> #include < ...
- 分区表在安装系统(MBR)丢失或损坏
操作系统能识别出硬盘中的各个不同的分区,是靠硬盘分区表(MBR)来识别的. 硬盘分区表中记录了各个分区的位置和大小以及类型等信息,假设这个分区表破坏了,那么这块硬盘里面的分区就会丢失.系统是无法在浏览 ...
- APUE学习笔记(1):APUE运行环境
APUE全称<Advanced Programming in the UNIX Environment>(UNIX环境高级编程) 书中例子大都使用作者自己写的头文件,所以需要解决一下,还好 ...
- Spring IOC 之Bean作用域
当你创建一个bean定义的时候,你创建了一份通过那种bean定义的bean的创建类的真正实力的处方.bean的定义是一个处方 的想法是很重要的的.因为这意味着,对于一个类你可以创建很多对象实例从一个单 ...
- Ora创建job定时执行某存储过程
--创建job任务,每天晚上8点执行存储过程:por_postrecords-- declare job number; begin sys.dbms_job.submit(job =>job, ...
- jQuery Easy UI LinkButton(button)包
LinkButton(button)包,easyui其中一个基本组成部分 演示样例: <!DOCTYPE html> <html> <head> <title ...
- MVC5系列——布局视图
MVC5系列——布局视图 目录 系列文章 概述 布局视图 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net MVC5系列——添加 ...
- MVC之验证
MVC之验证 有时候我觉得,很多人将一个具体的技术细节写的那么复杂,我觉得没有必要,搞得很多人一头雾水的,你能教会别人用就成了,具体的细节可以去查MSDN什么的,套用爱因斯坦的名言:能在网上查到的就不 ...
- MVC 5 的 EF6 Code First 入门 系列:排序、筛选和分页
这是微软官方SignalR 2.0教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里是第三篇:排序.筛选 ...