( _(:3 」∠)_给园友们提个建议,无论是API文档还是书籍,一定要多看几遍!特别是隔一段时间后,会有意想不到的收获的)
 
这篇文章主要是写关于学习react中的一些自己的思考:
 
1.setState到底是同步的还是异步的?
2.如何在子组件中改变父组件的state
3.context的运用,避免“props传递地狱”
4.组件类里有私有变量a,它到底改放在this.a中还是this.state对象中(作为属性a)呢?
 

setState到底是同步的还是异步的?

class MyComponent extends React.Component{
constructor(props) {
super(props)
this.state ={
value:0
}
}
handleClick = () => {
this.setState({value:1})
console.log('在handleClick里输出' + this.state.value);
}
render(){
console.log('在render()里输出' + this.state.value);
return (<div>
<button onClick ={this.handleClick}>按钮</button>
</div>)
}
}
export default MyComponent
//省略渲染过程,下面也一样
 
在这里我们点击按钮时,调用handleClick函数,首先调用this.setState()设置value,随即把this.state.value输出,结果是什么?
你可能会想,这还不简单——“在handleClick里输出1”呗,然而你错了,它的结果为:
 
事实上,setState()的调用大多数时候是异步的,这意味着,虽然你调用了setState({value:0}),但this.state.value并不会马上变成0,而是直到render()函数调用时,setState()才真正被执行。结合图说明一下:
 
你可能又会问了:要是我在render()前多次调用this.setState()改变同一个值呢?(比如value)
 
我们对handleClick做一些修改,让它变得复杂一点,在调用handleClick的时候,依次调用handleStateChange1 ,handleStateChange2,handleStateChange3,它们会调用setState分别设置value为1,2,3并且随即打印
handleStateChange1 = () => {
this.setState({value:1})
console.log('在handleClick里输出' + this.state.value);
}
handleStateChange2 = () => {
this.setState({value:2})
console.log('在handleClick里输出' + this.state.value);
}
handleStateChange3 = () => {
this.setState({value:3})
console.log('在handleClick里输出' + this.state.value);
}
handleClick = () => {
this.handleStateChange1();
this.handleStateChange2();
this.handleStateChange3();
}
 
那么输出结果会是什么呢?如果setState总是同步调用的,那么结果显然为
在handleClick里输出1
在handleClick里输出2
在handleClick里输出3
 
但是结果为:,证明它可能是异步的
 
这下好理解了吧,配合这幅图:

setSate大部分的时候是异步执行的,但是,在react本身监听不到的地方,如原生js的监听里,setInterval,setTimeout里,setState就是同步更新的

关于更多React的异步同步问题请点击这里

如何在子组件中改变父组件的state?

这是我们经常会遇到的问题之一,解决办法是:在父组件中写一个能改变父组件state的方法,并通过props传入子组件中
class Son extends React.Component{
render(){
return(<div onClick = {this.props.handleClick}>
{this.props.value}
</div>)
}
}
class Father extends React.Component{
constructor(props){
super(props)
this.state ={
value:'a'
}
}
handleClick = () => {
this.setState({value:'b'})
}
render(){
return (<div style ={{margin:50}}>
<Son value = {this.state.value} handleClick = {this.handleClick}/>
</div>)
}
}
 
点击子组件Son,内容由a变成b,说明父组件的state被修改了

context的运用,避免“props传递地狱”

 
3.1假设一个比较极端的场景:你需要从你的子组件里调用父父父父父组件的属性或方法,怎么办!当组件嵌套层级过深的时候,不断地传props作为实现方式简直就是噩梦!我称之为“props传递地狱”(这个词是我瞎编的,参考自“回调函数地狱”)
 
我们接下来实现的是这样一个需求,把gene属性(基因)从组件GrandFather -->Father --> Son传递,如果用props传递:
class Son extends React.Component{
render(){
return (<h3 style ={{marginTop:30}}>我从我的爷爷那里得到了基因--{this.props.gene}</h3>)
}
}
class Father extends React.Component{
render(){
return (<Son gene = {this.props.gene}/>)
}
}
class GrandFather extends React.Component{
constructor(props) {
super(props)
this.state ={
gene:'[爷爷的基因]'
}
}
render(){
return (<Father gene = {this.state.gene}/>)
}
}
demo:
 
【(。・`ω´・)虽然听起来有点怪怪的但是大家别介意哈】
 
实现是实现了,但你想想,假设不是从“爷爷”组件,而是从“太太太太爷爷”组件传下来,这多可怕!不过没关系,react提供了一个叫做context(上下文)的API,你在顶层组件的context中定义的属性,可以在所有的后代组件中,通过this.context.属性去引用!让我们一睹为快:
class Son extends React.Component{
render(){
console.log(this.context.color);
return (<h3 style ={{marginTop:30}}>我从我的爷爷那里得到了基因--{this.context.gene}</h3>)
}
}
Son.contextTypes ={
gene:React.PropTypes.string
}
class Father extends React.Component{
render(){
return (<Son/>)
}
}
class GrandFather extends React.Component{
getChildContext(){
return {gene:'[爷爷的基因]'}
}
render(){
return (<Father />)
}
}
GrandFather.childContextTypes = {
gene: React.PropTypes.string
};
export default GrandFather
demo效果同上!这个时候你发现,我们在<GrandFather>组件和<Father>组件中都没有向下传递props,我们就从最下层的Son组件中获取了gene属性,是不是很方便!
 
解释下代码:
getChildContext()是你在顶层组件中定义的钩子函数,这个函数返回一个对象——你希望在后代组件中取用的属性就放在这个对象中,譬如这个例子中我希望在Son组件中通过this.context.gene取属性,所以在getChildContext()中返回{gene:'[爷爷的基因]'}
GrandFather.childContextTypes和Son.contextTypes 用于规定顶层组件和取顶层组件context的后代组件的属性类型
 
【注意】GrandFather.childContextTypes和Son.contextTypes 这两个对象必须要规定!否则context只能取到空对象!一开始我犯的这个错误简直让我狂吐三升血。。。。
 
有图有真相之context和props的区别
 
3.2context是否推荐使用?
虽然上面这个例子说明了context多么好用,但注意:官方并不推荐经常使用它,因为它会让你的应用架构变得不稳定(官方文档原话If you want your application to be stable, don't use context),在我看来,为什么在大多数情况下要使用props而不是实现数据流呢,因为props凭借组件和组件间严密的逻辑联系,使得你能够清晰地跟踪应用的数据流(it's easy to track the flow of data through your React components with props)当然了,如果你遇到上述的例子的情况,context还是大有裨益的

 
3.3需要改变context中的属性时候,不要直接改变它,而是使用this.state作为媒介,如果你试图在顶层组件的state中放入一个可变的属性你可以这样做:
getChildContext(){
return {type:this.state.type}
}
 
3.4在上述我限制gene的类型时候我是这样写的:gene: React.PropTypes.string,使用了React内置的React.PropTypes帮助属性,此时我的版本为 "react": "15.4.2",在15.5的版本后这一帮助属性被废弃,推荐使用props-types库,像这样:
const PropTypes = require("Prop-Types");
GrandFather.childContextTypes = {
gene: PropTypes.string
};
 
当然,在这之前你需要npm install prop-types
 

组件类里有私有变量a,它到底改放在this.a中还是this.state对象中(作为属性a)呢?

这得根据它是否需要实时的重渲染决定,如果该变量需要同步到变化的UI中,你应该把它放在this.state对象中,如果不需要的话,则把它放在this中(无代码无demo)
 
【完】--喜欢这篇文章的话不妨关注一下我哟

【react学习】关于react框架使用的一些细节要点的思考的更多相关文章

  1. 【react】关于react框架使用的一些细节要点的思考

    ( _(:3 」∠)_给园友们提个建议,无论是API文档还是书籍,一定要多看几遍!特别是隔一段时间后,会有意想不到的收获的)   这篇文章主要是写关于学习react中的一些自己的思考:   1.set ...

  2. React 学习(一) ---- React Element /组件/JSX

    学习React的时候,你可能听到最多的就是要先学习webpack, babel,要先学会配置然后才能学react 等等,一堆的配置就把我们吓着了,根本就没有心情就学习react了.其实在最开始学习re ...

  3. AntDesign(React)学习-3 React基础

    前面项目已经建起来了,但是没有React基础怎么办,从头学习,这个项目使用的是基于React16.X版本的几种技术集成,那么我们就从网上找一些相关的资料进行研究,我的习惯是用到哪学到哪. 一.先看一些 ...

  4. AntDesign(React)学习-1 创建环境

    目录: AntDesign(React)学习-15 组件定义.connect.interface AntDesign(React)学习-14 使用UMI提供的antd模板 AntDesign(Reac ...

  5. react基础学习和react服务端渲染框架next.js踩坑

    说明 React作为Facebook 内部开发 Instagram 的项目中,是一个用来构建用户界面的优秀 JS 库,于 2013 年 5 月开源.作为前端的三大框架之一,React的应用可以说是非常 ...

  6. React学习笔记。

    有段时间没写博客了,最近这段时间有点说不出的苦,虽然说年轻的时候该多出去经历些事,但每次找工作东跑西跑,坐公交坐地铁浪费了我太多时间,我感觉到这是一种浪费,对生命的浪费.所以很想尽快找到一份工作,去努 ...

  7. React学习笔记-1-什么是react,react环境搭建以及第一个react实例

    什么是react?react的官方网站:https://facebook.github.io/react/下图这个就是就是react的标志,非常巧合的是他和我们的github的编辑器Atom非常相似. ...

  8. react学习小结(生命周期- 实例化时期 - 存在期- 销毁时期)

    react学习小结   本文是我学习react的阶段性小结,如果看官你是react资深玩家,那么还请就此打住移步他处,如果你想给一些建议和指导,那么还请轻拍~ 目前团队内对react的使用非常普遍,之 ...

  9. React学习笔记(一) 基础知识

    现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我. React的基 ...

随机推荐

  1. Spark集群搭建_YARN

    2017年3月1日, 星期三 Spark集群搭建_YARN 前提:参考Spark集群搭建_Standalone   1.修改spark中conf中的spark-env.sh   2.Spark on ...

  2. 信号处理——傅里叶变换(FT-DTFT-DFT)

    作者:桂. 时间:2017-01-17  23:41:13 链接:http://www.cnblogs.com/xingshansi/articles/6294111.html 声明:转载请注明出处, ...

  3. Collection和Map

    (1)Collection和Map的继承体系. (2)ArrayList(数组).LinkedList(链表).Vector(线程同步).Stack(继承Vector先进后出的栈).PriorityQ ...

  4. 浅析=======Struts2之==========valueStack

    今天刚学习了struts2的valueStack,在这里把自己学到的做个分享,说道valueStack就不得不提OGNL表达式=== struts2工作流程 1.OGNL(Object Graph N ...

  5. 关于nodeJS多线程的支持,目前看来无法实现,讲解v8的一些东西

    关于这个,我这几天一直在研究,国内关于v8的资料很少,stackoverflow上也不多. 说起来我得说声抱歉,虽然并没有承诺什么.这个功能大概是无法实现.下面我来解释一下为什么. 首先我们要了解一下 ...

  6. 1491: [NOI2007]社交网络

    1491: [NOI2007]社交网络 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 881  Solved: 518[Submit][Status] ...

  7. Archlinux中卸载 Slim

    Slim 是图形登录器.最近停止更新了,据说在systemd中有兼容性问题. 卸载Slim的原因是某计算机使用的是AMD显卡的Catalyst驱动,图形驱动一旦出问题,Slim就无法启动,给维护造成困 ...

  8. Python中参数是传值,还是传引用?

    在 C/C++ 中,传值和传引用是函数参数传递的两种方式,在Python中参数是如何传递的?回答这个问题前,不如先来看两段代码. 代码段1: def foo(arg): arg = 2 print(a ...

  9. ASP.NET MVC创建视图过程

    MvcHandler.ProcessRequest()   (1)获取Action执行结果:context2.Result ActionExecutedContext context2 = this. ...

  10. 隐性URL与显性URL区别与SEO考虑

    隐性URL与显性URL经常在实现页面跳转的时候用到,这两种方式有什么区别,各自对SEO有什么影响?看一下阿里云的官方文档解释: 显性URL转发: 例如: http://b.com/ 指向 http:/ ...