简体   繁体   English

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

[英]React Form controlled by a Flux Store (Best practice?)

So I have a big component that would be my form: 所以我有一个很重要的组成部分:

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

This form component is listening for a store that updates its values using firstAction , secondAction , etc. 此表单组件正在侦听使用firstActionsecondAction等更新其值的存储。

Note: Component updates its state based on store.getState() that returns {firstValue: something, secondValue: something, etc} 注意:组件基于store.getState()更新其状态,返回{firstValue: something, secondValue: something, etc}

So let's say my FirstComponent is an input: 那么让我们说我的FirstComponent是一个输入:

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

Ok, so the onChange fires the prop firstAction which is actually the Flux action that will update my store and make the form to re-render. 好的,所以onChange触发了prop的firstAction ,它实际上是Flux动作,它将更新我的商店并使表单重新渲染。 I have two good things here, when user submits the form, I can check the value of FirstComponent in my store and I also control all my state from the parent component. 我有两个好东西,当用户提交表单时,我可以检查我的商店中的FirstComponent的值,并且我还控制来自父组件的所有状态。

However, this onChange callback will call an action every time the user types one character (so it can produce a lot of calls therefore re-renders) <-- can this provoke serious performance issues? 但是,每次用户键入一个字符时,此onChange回调将调用一个操作(因此它可以产生大量调用,因此重新渲染)< - 这会引发严重的性能问题吗?

Instead, I could use refs and when the user press the submit button, get this.refs.myFirstComponent.state ... and I will have the value too (that would be Uncontrolled Component ?) But this does not sound like a recommendation from the community. 相反,我可以使用refs,当用户按下提交按钮时,获取this.refs.myFirstComponent.state ...我也将获得该值(这将是Uncontrolled Component ?)但这听起来不像是来自社区。

So my question is, is the first approach I described above a good way to go? 所以我的问题是,我上面描述的第一种方法是一个很好的方法吗? How can I optimize it? 我该如何优化它? So a re-render that should only affect FirstComponent does not make SecondComponent and so on to re-render? 那么只应该影响FirstComponent的重新渲染不会使SecondComponent等重新渲染? Is shouldComponentUpdate the only way to go here? shouldComponentUpdate是唯一的方法吗?


Edit 1: 编辑1:

With the first approach I am facing a problem... I have an e2e test using WebdriverIO adding a value into the text field: http://webdriver.io/api/action/setValue.html 第一种方法我面临一个问题......我使用WebdriverIO进行e2e测试,在文本字段中添加一个值: http ://webdriver.io/api/action/setValue.html

I don't know why but if I am trying to add the word "Testing" into the input, webdriver will only add the last letter. 我不知道为什么,但如果我试图在输入中添加“测试”这个词,webdriver只会添加最后一个字母。 This problem is gone if not using state/store at all. 如果不使用状态/存储,这个问题就消失了。 However, if I have the state internally to my FirstComponent , something like: 但是,如果我在我的FirstComponent内部有状态,例如:

<input type="text" value={this.state.value} 
   onChange={(e)=>this.setState({firstValue: e.target.value})}
   onBlur={()=>this.props.callback(this.state.firstValue)}
</input>

In this case, component seems to react faster while typing (only renders itself), and then, when user removes focus it updates the store. 在这种情况下,组件在键入时似乎反应更快(仅渲染自身),然后,当用户移除焦点时,它会更新商店。 I have to say, I don't like this approach because it doesn't follow the pattern of take your state up (and I feel I am duplicating the state) BUT it seems to work faster and more important: My e2e test works. 我不得不说,我不喜欢这种方法,因为它不遵循你的状态(我觉得我复制状态)的模式但是它似乎工作得更快更重要:我的e2e测试工作。 Any more ideas? 还有什么想法吗?

Your first approach (ie onChange fires flux action which updates the store and make your form re-render) seems like a good way to go. 你的第一种方法(即onChange fires flux动作更新商店并使你的表格重新渲染)似乎是一个很好的方法。 I've been using it like that and I've seen other people using it like that, too. 我一直在使用它,我也见过其他人也这样使用它。

Regarding your following comment: 关于您的以下评论:

However, this onChange callback will call an action every time the user types one character (so it can produce a lot of calls therefore re-renders) <-- can this provoke serious performance issues? 但是,每次用户键入一个字符时,此onChange回调将调用一个操作(因此它可以产生大量调用,因此重新渲染)< - 这会引发严重的性能问题吗?

Yes, I believe so. 是的,我相信。 I once created a component that contains many other components along with some input fields. 我曾经创建了一个包含许多其他组件的组件以及一些输入字段。 Whenever I typed a character in an input field, the whole component (with other components it includes and the input fields) got re-rendered, causing the performance problem. 每当我在输入字段中输入一个字符时,整个组件(包含其他组件和输入字段)都会被重新渲染,从而导致性能问题。 It was noticeable if I typed fast. 如果我快速键入,这是显而易见的。 You can actually verify it using https://facebook.github.io/react/docs/perf.html . 您可以使用https://facebook.github.io/react/docs/perf.html实际验证它。

Anyway, how I got around the problem is, as you mentioned, by implementing shouldComponentUpdate() . 无论如何,正如你所提到的,我如何解决这个问题是通过实现shouldComponentUpdate()

A small tip I'd like to mention is creating a custom <Input /> component that wraps around <input /> and implementing shouldComponentUpdate() (ie this.props.value !== nextProps.value || this.props.checked !== nextProps.checked ) That way, if you create a form component, for example, with many input fields (using the custom <Input /> ), only the input field that is changed gets re-rendered. 我想提一个小技巧是创建一个自定义<Input />组件,它包含<input />并实现shouldComponentUpdate() (即this.props.value !== nextProps.value || this.props.checked !== nextProps.checked )这样,如果您创建一个表单组件,例如,使用许多输入字段(使用自定义<Input /> ),则只会重新呈现更改的输入字段。

I'd love to see how other people approach this problem, too, though. 不过,我也很想知道其他人是如何处理这个问题的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM