这篇文章主要是写关于学习react中的一些自己的思考:
1.setState到底是同步的还是异步的?
2.如何在子组件中改变父组件的state
3.context的运用,避免“props传递地狱”
4.组件类里有私有变量a,它到底改放在this.a中还是this.state对象中(作为属性a)呢?
1.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 但是结果为:,证明它是异步的 这下好理解了吧,配合这幅图:
2.如何在子组件中改变父组件的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被修改了 3.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 GrandFatherdemo效果同上!这个时候你发现,我们在<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而不是实现html" target="_blank">数据流呢,因为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
以上这篇基于react框架使用的一些细节要点的思考就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持小牛知识库。
在Doug Lea的论文“A Java Fork/Join Framework”中: http://gee.cs.oswego.edu/dl/papers/fj.pdf 在2.1偷工中,他说: 当工作线程遇到连接操作时,它会处理其他任务(如果可用),直到注意到目标任务已完成(通过isDone)。否则,所有任务都将在不阻塞的情况下运行到完成。 那么有人能具体告诉我这些“其他任务”来自哪里吗?它们来自
问题内容: 我想知道人们对通过LINQ-to-SQL支持实体框架的决定有何想法?我有一个我最初使用LINQ-to- SQL开发的应用程序。我发现它是我们应用的理想解决方案。 在尝试移植到Entity Framework时,我感到很惊讶。恕我直言,甚至还没有准备好黄金时间。没有延迟加载,没有POCO,对继承的可怕依赖。我发现它在我的情况下基本上不可用,而是决定坚持使用LINQ- to-SQL,直到以
本文向大家介绍oracle更新xml节点问题的一些细节,包括了oracle更新xml节点问题的一些细节的使用技巧和注意事项,需要的朋友参考一下 有的节点是<emali/> 这样的,所以直接 是不能更新的 这样就能更新了
我正在使用Jison编写一个解析器,它允许我解析一种相当复杂的表达式语言。在这种语言中,它支持语法,如: 这里的eval_表达式非常复杂(具有嵌套eval、逻辑表达式等功能),我不关心eval_表达式的内容,也不想花费太多精力解析它。我只想获得上述语法中的其他信息,比如stats_函数名。 我的问题是,在Jison中是否有任何方法允许我做一些通配符匹配来轻松匹配整个eval_expression,
pbgo是我们专门针对本节内容设计的较为完整的迷你框架,它基于Protobuf的扩展语法,通过插件自动生成rpc和rest相关代码。在本章第二节我们已经展示过如何定制一个Protobuf代码生成插件,并生成了rpc部分的代码。在本节我们将重点讲述pbgo中和Protobuf扩展语法相关的rest部分的工作原理。 4.7.1 Protobuf扩展语法 目前Protobuf相关的很多开源项目都使用到了