State 与 Props 区别
props 是组件对外的接口,state 是组件对内的接口。组件内可以引用其他组件,组件之间的引用形成了一个树状结构(组件树),如果下层组件需要使用上层组件的数据或方法,上层组件就可以通过下层组件的props属性进行传递,因此props是组件对外的接口。组件除了使用上层组件传递的数据外,自身也可能需要维护管理数据,这就是组件对内的接口state。根据对外接口props 和对内接口state,组件计算出对应界面的UI。

主要区别:

State是可变的,是一组用于反映组件UI变化的状态集合;
而Props对于使用它的组件来说,是只读的,要想修改Props,只能通过该组件的父组件修改。
在组件状态上移的场景中,父组件正是通过子组件的Props, 传递给子组件其所需要的状态。
Props的使用
当一个组件被注入一些属性(Props )值时,属性值来源于它的父级元素,所以人们常说,属性在 React 中是单向流动的:从父级到子元素。

######1、props(属性) 默认为 “true”
如果你没给 prop(属性) 传值,那么他默认为 true 。下面两个 JSX 表达式是等价的:

通常情况下,我们不建议使用这种类型,因为这会与ES6中的对象shorthand混淆 。ES6 shorthand 中 {foo} 指的是 {foo: foo} 的简写,而不是 {foo: true} 。这种行为只是为了与 HTML 的行为相匹配。
(举个例子,在 HTML 中,< input type=“radio” value=“1” disabled /> 与 < input type=“radio” value=“1” disabled=“true” /> 是等价的。JSX 中的这种行为就是为了匹配 HTML 的行为。)
######2、props扩展
如果你已经有一个 object 类型的 props,并且希望在 JSX 中传入,你可以使用扩展操作符 … 传入整个 props 对象。这两个组件是等效的:

显然下面的方法更方便:因为它将数据进行了包装,而且还简化了赋值的书写

State
一、State是什么?

React 的核心思想是组件化,而组件中最重要的概念是State(状态),State是一个组件的UI数据模型,是组件渲染时的数据依据。

状态(state) 和 属性(props) 类似,都是一个组件所需要的一些数据集合,但是state是私有的,可以认为state是组件的“私有属性(或者是局部属性)”。

如何判断是否为State ?
组件中用到的一个变量是不是应该作为组件State,可以通过下面的4条依据进行判断:

这个变量是否是通过Props从父组件中获取?如果是,那么它不是一个状态。
这个变量是否在组件的整个生命周期中都保持不变?如果是,那么它不是一个状态。
这个变量是否可以通过其他状态(State)或者属性(Props)计算得到?如果是,那么它不是一个状态。
这个变量是否在组件的render方法中使用?如果不是,那么它不是一个状态。这种情况下,这个变量更适合定义为组件的一个普通属性,例如组件中用到的定时器,就应该直接定义为this.timer,而不是this.state.timer。

并不是组件中用到的所有变量都是组件的状态!当存在多个组件共同依赖一个状态时,一般的做法是状态上移,将这个状态放到这几个组件的公共父组件中。

二、如何正确使用 State
1、用setState 修改State

直接修改state,组件并不会重新触发render()

正确的修改方式是使用setState()

2、State 的更新是异步的

调用setState后,setState会把要修改的状态放入一个队列中(因而 组件的state并不会立即改变);
之后React 会优化真正的执行时机,来优化性能,所以优化过程中有可能会将多个 setState 的状态修改合并为一次状态修改,因而state更新可能是异步的。
所以不要依赖当前的State,计算下个State。当真正执行状态修改时,依赖的this.state并不能保证是最新的State,因为React会把多次State的修改合并成一次,这时,this.state将还是这几次State修改前的State。
另外需要注意的事,同样不能依赖当前的Props计算下个状态,因为Props一般也是从父组件的State中获取,依然无法确定在组件状态更新时的值。

综上所述:
this.props 和 this.state 可能是异步更新的,你不能依赖他们的值计算下一个state(状态)

例:
这样 counter(计数器)会更新失败

要弥补这个问题,使用 setState() 的另一种形式,它接受一个函数而不是一个对象。这个函数有两个参数:
(1)第一个参数: 是当前最新状态的前一个状态(本次组件状态修改前的状态),就是更新前的状态(this.state)
(2)第二个参数:是当前最新的属性props

如果你还不懂没关系,看下面例子:
我们现在渲染出一个button,想每点击一下,counter就+3
看下面代码:

输出:

每点击一下,加+1,并不是+3

之所以+1,不是+3,是因为 state 的更新可能是异步的,React 会把传入多个 setState的多个 Object “batch” 起来合并成一个。

合并成一个就相当于把传入 setState 的多个 Object 进行 shallow merge,像这样:

我们可以这么做就会成功:看下面

之所以成功是因为:传入多个 setState 的多个 Object 会被 shallow Merge,而传入多个 setState 的多个 function 会被 "queue" 起来,

queue 里的 function 接收到的 state(上面是 prev )都是前一个 function 操作过的 state。

3、State更新会被合并
官方文档看不懂不要紧,直接举个例子你就懂了。

例如一个组件的状态为:

当只需要修改状态title时,只需要将修改后的title传给setState:

React会合并新的title到原来的组件状态中,同时保留原有的状态content,合并后的State为:

4、setState里顺序更新

执行setState时:先更新history,然后再用更新改变后的history计算current的值,最后再更新nextPlayer

三、根据State类型 更新
当状态发生变化时,如何创建新的状态?根据状态的类型,可以分成三种情况:

1、 状态的类型是不可变类型(数字,字符串,布尔值,null, undefined)

这种情况最简单,直接给要修改的状态赋一个新值即可

2、 状态的类型是数组
数组是一个引用,React 执行 diff 算法时比较的是两个引用,而不是引用的对象。所以直接修改原对象,引用值不发生改变的话,React 不会重新渲染。因此,修改状态的数组或对象时,要返回一个新的数组或对象。
(1)增加
如有一个数组类型的状态books,当向books中增加一本书(chinese)时,使用数组的concat方法或ES6的数组扩展语法

(2)截取
当从books中截取部分元素作为新状态时,使用数组的slice方法:

(3)条件过滤
当从books中过滤部分元素后,作为新状态时,使用数组的filter方法:

3、状态的类型是普通对象(不包含字符串、数组)
对象是一个引用,React 执行 diff 算法时比较的是两个引用,而不是引用的对象。所以直接修改原对象,引用值不发生改变的话,React 不会重新渲染。因此,修改状态的数组或对象时,要返回一个新的对象。
使用ES6 的Object.assgin方法

使用对象扩展语法(object spread properties)

> 综上所述: > 创建新的状态对象的关键是,`避免使用会直接修改原对象的方法,而是使用可以返回一个新对象的方法。`
四、State向下流动
我们说 props 是组件对外的接口,state 是组件对内的接口。
一个组件可以选择将 state(状态) 向下传递,作为其子组件的 props(属性):

这通常称为一个“从上到下”,或者“单向”的数据流。任何 state(状态) 始终由某个特定组件所有,并且从该 state(状态) 导出的任何数据 或 UI 只能影响树中 “下方” 的组件。

如果把组件树想像为 props(属性) 的瀑布,所有组件的 state(状态) 就如同一个额外的水源汇入主流,且只能随着主流的方向向下流动。
----------------------------------------------------------------------------------------------------

原文:https://blog.csdn.net/b954960630/article/details/79822639

React学习:状态(State) 和 属性(Props)的更多相关文章

  1. (组件的)状态(state)和属性(props)之间有何不同

    State 是一种数据结构,用于组件挂载时所需数据的默认值.State 可能会随着时间的推移而发生突变,但多数时候是作为用户事件行为的结果.Props(properties 的简写)则是组件的配置.p ...

  2. React 学习(三) ---- state 和 事件处理函数

    在上两节中,我们讲述了props, 组件使用props进行渲染,但是这是一次性的, props渲染完成之后就不做任何事情了,但是现实中却不是这样的,当我们点击购物车上的加减按钮时,数量会自动加1或减1 ...

  3. React学习之State

    本文基于React v16.4.1 初学react,有理解不对的地方,欢迎批评指正^_^ 一.定义组件的两种方式 1.函数定义组件 function Welcome(props) { return & ...

  4. react设置默认state和默认props

    1.默认状态设置 1.constructor (ES6) constructor(props) { this.state = { n: ... } } 2.getInitialState (ES5) ...

  5. react学习记录(三)——状态、属性、生命周期

    react的状态state React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM) class Clock extends React.Compon ...

  6. React组件系统、props与状态(state)

     多个组件合成一个组件: var style = { fontSize: 20, color: '#ff0000' }; var WebSite = React.createClass({ rende ...

  7. React 学习(二) ---- props验证与默认属性

    在上一节中, 我们提到了props, 组件之间数据的传递使用props. 我们调用组件时可以设置props, 组件内部通过props获取. 为了props 使用更加友好, React 提供了简单的验证 ...

  8. React学习笔记(五)State&声明周期

    React学习笔记(五) 四.State&声明周期 可以为组件添加"状态(state)".状态与属性相似,但是状态是私有的,完全受控于当前组件. 局部状态就是只能用于类(定 ...

  9. React Native 快速入门之认识Props和State

    眼下React Native(以后简称RN)越来越火,我也要投入到学习当中.对于一个前端来说,还是有些难度.因为本人觉得这是一个App开发的领域,自然是不同.编写本文的时候,RN的版本为0.21.0. ...

随机推荐

  1. server2003 IIS6.0 网站不可用

    事件 ID ( 487 )的描述(在资源( Zend Optimizer )中)无法找到.本地计算机可能没有必要的注册信息或消息 DLL 文件来从远程计算机显示消息.您可能可以使用 /AUXSOURC ...

  2. Error:(23, 0) Could not find method implementation() for arguments [directory 'libs'] on object of t

    Error:(28, 0) Could not find method implementation() for arguments [com.android.support:appcompat-v7 ...

  3. 对异步处理的http接口进行性能测试

    以前对接口做性能测试,接口都是同步处理的,请求之后等待响应结果就知道处理结果了,这样只要看这个接口是否异常,如果无异常无报错记录这个接口的响应时间.TPS等性能指标进行分析就可以了,最近在工作中遇到了 ...

  4. http statusCode(状态码)请求URL返回状态值的含义

    http statusCode(状态码)请求URL返回状态值的含义 请求URL浏览器返回状态码的含义(http statusCode): 201-206都表示服务器成功处理了请求的状态代码,说明网页可 ...

  5. [E2E_L7 51CTO]初步接触OpenVINO提供的例子(win+vs)

    一.例子编译 1.运行 C:\Program Files (x86)\IntelSWTools\openvino_2019.1.148\bin\setupvars.bat 这步需要win平台下安装py ...

  6. Xamarin图表开发基础教程(11)OxyPlot框架支持的图表类型

    Xamarin图表开发基础教程(11)OxyPlot框架支持的图表类型 OxyPlot组件中支持7种类型的条型图表,分别为普通条形图.线型条形图.矩形条形图.差值图.龙卷风图.普通柱形图和柱形误差图, ...

  7. git用法汇总

    使用了一年多的git命令了,昨晚竟然又出现了问题.虽然解决了,不过还是被罚了... 总结下自己常用的git命令和遇到的一些坑. 1)常用的命令 1. 从git远程分支clone代码: git clon ...

  8. Postman:上传文件测试

    1.设置好接口地址与提交方法 2.设置header Content-Type:multipart/form-data 3.设置body 选择为:form-data key要和服务器端保持一致 选择好自 ...

  9. 使用二进制的方式部署 K8S-1.16 高可用集群

    一.项目介绍 项目致力于让有意向使用原生kubernetes集群的企业或个人,可以方便的.系统的使用二进制的方式手工搭建kubernetes高可用集群.并且让相关的人员可以更好的理解kubernete ...

  10. Linq调试实时输出信息扩展方法(摘抄)

    原文在此 [译]如何在C#中调试LINQ查询 原linq语句: var res = employees .Where(e => e.Gender == "Male") .Ta ...