由Flux Store控制的React Form(最佳实践?)

时间:2015-07-30 23:42:59

标签: javascript forms reactjs reactjs-flux

所以我有一个很重要的组成部分:

<form>
 <FirstComponent value={this.state.firstValue}/>
 <SecondComponent value={this.state.secondValue}/>
 {more components here}
 <input type="submit" ... />
</form>

此表单组件正在侦听使用firstActionsecondAction等更新其值的商店。

注意:组件根据返回{firstValue: something, secondValue: something, etc}

的store.getState()更新其状态

所以,让我们说FirstComponent是一个输入:

<input type="text" value={this.props.value} 
   onChange={(e)=>this.props.firstAction(e.target.value)}
</input>

好的,onChange会触发道具firstAction,这实际上是Flux操作,它将更新我的商店并使表单重新渲染。我在这里有两件好事,当用户提交表单时,我可以检查商店中FirstComponent的值,并且我还可以控制父组件中的所有状态。

但是,每次用户键入一个字符时,此onChange回调都会调用一个操作(因此它可以产生大量调用,因此重新渲染)&lt; - 这会引发严重的性能问题吗?

相反,我可以使用引用,当用户按下提交按钮时,获取this.refs.myFirstComponent.state ...我也会得到值(那将是Uncontrolled Component?)但这听起来不是喜欢来自社区的推荐。

所以我的问题是,上面描述的第一种方法是一个很好的方法吗?我该如何优化它?那么只应该影响FirstComponent的重新渲染不会使SecondComponent等重新渲染? shouldComponentUpdate是到这里的唯一途径吗?

修改1:

使用第一种方法我遇到了问题...我使用WebdriverIO进行了e2e测试,在文本字段中添加了一个值:http://webdriver.io/api/action/setValue.html

我不知道为什么,但如果我想添加“#34;测试&#34;进入输入,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 个答案:

答案 0 :(得分:3)

您的第一种方法(即onChange触发助焊剂操作,更新商店并使您的表单重新渲染)似乎是一个很好的方法。我一直在使用它,我也看到其他人也这样使用它。

关于您的以下评论:

  

但是,每次用户输入一个字符时,这个onChange回调都会调用一个动作(因此它可以产生大量的调用,因此重新渲染)&lt; - 这会引发严重的性能问题吗?

是的,我相信。我曾经创建了一个包含许多其他组件的组件以及一些输入字段。每当我在输入字段中输入一个字符时,整个组件(包含其他组件和输入字段)都会被重新渲染,从而导致性能问题。如果我快速键入,这是显而易见的。您可以使用https://facebook.github.io/react/docs/perf.html实际验证它。

无论如何,正如你所提到的,我如何解决这个问题是通过实施shouldComponentUpdate()

我想提到的一个小提示是创建一个自定义<Input />组件,其中包含<input />并实现shouldComponentUpdate()(即this.props.value !== nextProps.value || this.props.checked !== nextProps.checked)这样,如果你例如,创建一个表单组件,包含许多输入字段(使用自定义<Input />),只有重新呈现的输入字段才会被重新呈现。

我也很想知道其他人如何解决这个问题。