问题描述
所以我有一个很重要的组成部分:
<form>
<FirstComponent value={this.state.firstValue}/>
<SecondComponent value={this.state.secondValue}/>
{more components here}
<input type="submit" ... />
</form>
此表单组件正在侦听使用firstAction
, secondAction
等更新其值的存储。
注意:组件基于store.getState()更新其状态,返回{firstValue: something, secondValue: something, etc}
那么让我们说我的FirstComponent
是一个输入:
<input type="text" value={this.props.value}
onChange={(e)=>this.props.firstAction(e.target.value)}
</input>
好的,所以onChange
触发了prop的firstAction
,它实际上是Flux动作,它将更新我的商店并使表单重新渲染。
我有两个好东西,当用户提交表单时,我可以检查我的商店中的FirstComponent的值,并且我还控制来自父组件的所有状态。
但是,每次用户键入一个字符时,此onChange
回调将调用一个操作(因此它可以产生大量调用,因此重新渲染)< - 这会引发严重的性能问题吗?
相反,我可以使用refs,当用户按下提交按钮时,获取this.refs.myFirstComponent.state
...我也将获得该值(这将是 ?)但这听起来不像是来自社区。
所以我的问题是,我上面描述的第一种方法是一个很好的方法吗?
我该如何优化它?
那么只应该影响FirstComponent的重新渲染不会使SecondComponent等重新渲染?
shouldComponentUpdate
是唯一的方法吗?
编辑1:
第一种方法我面临一个问题......我使用WebdriverIO进行e2e测试,在文本字段中添加一个值: ://webdriver.io/api/action/setValue.html
我不知道为什么,但如果我试图在输入中添加“测试”这个词,webdriver只会添加最后一个字母。
如果不使用状态/存储,这个问题就消失了。
但是,如果我在我的FirstComponent
内部有状态,例如:
<input type="text" value={this.state.value}
onChange={(e)=>this.setState({firstValue: e.target.value})}
onBlur={()=>this.props.callback(this.state.firstValue)}
</input>
在这种情况下,组件在键入时似乎反应更快(仅渲染自身),然后,当用户移除焦点时,它会更新商店。 我不得不说,我不喜欢这种方法,因为它不遵循你的状态(我觉得我复制状态)的模式但是它似乎工作得更快更重要:我的e2e测试工作。 还有什么想法吗?
1楼
Brian Park
3
2015-07-31 03:30:16
你的第一种方法(即onChange
fires flux动作更新商店并使你的表格重新渲染)似乎是一个很好的方法。
我一直在使用它,我也见过其他人也这样使用它。
关于您的以下评论:
但是,每次用户键入一个字符时,此onChange回调将调用一个操作(因此它可以产生大量调用,因此重新渲染)< - 这会引发严重的性能问题吗?
是的,我相信。 我曾经创建了一个包含许多其他组件的组件以及一些输入字段。 每当我在输入字段中输入一个字符时,整个组件(包含其他组件和输入字段)都会被重新渲染,从而导致性能问题。 如果我快速键入,这是显而易见的。 您可以使用实际验证它。
无论如何,正如你所提到的,我如何解决这个问题是通过实现shouldComponentUpdate()
。
我想提一个小技巧是创建一个自定义<Input />
组件,它包含<input />
并实现shouldComponentUpdate()
(即this.props.value !== nextProps.value || this.props.checked !== nextProps.checked
)这样,如果您创建一个表单组件,例如,使用许多输入字段(使用自定义<Input />
),则只会重新呈现更改的输入字段。
不过,我也很想知道其他人是如何处理这个问题的。