由 Flux Store 控制的 React Form(最佳实践?)
Posted
技术标签:
【中文标题】由 Flux Store 控制的 React Form(最佳实践?)【英文标题】:React Form controlled by a Flux Store (Best practice?) 【发布时间】:2015-10-22 12:35:19 【问题描述】:所以我有一个很大的组件就是我的表单:
<form>
<FirstComponent value=this.state.firstValue/>
<SecondComponent value=this.state.secondValue/>
more components here
<input type="submit" ... />
</form>
此表单组件正在侦听使用 firstAction
、secondAction
等更新其值的商店。
注意:组件根据返回 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
回调会在用户每次输入一个字符时调用一个动作(因此它会产生大量调用,因此会重新渲染)
相反,我可以使用 refs,当用户按下提交按钮时,得到 this.refs.myFirstComponent.state
... 我也将拥有该值(那将是 Uncontrolled Component?)但这听起来不像是来自社区。
所以我的问题是,我上面描述的第一种方法是一个好方法吗?我该如何优化它?那么应该只影响 FirstComponent 的重新渲染不会使 SecondComponent 等重新渲染? shouldComponentUpdate
是唯一的途径吗?
编辑 1:
第一种方法我面临一个问题...我有一个使用 WebdriverIO 的 e2e 测试,在文本字段中添加一个值:http://webdriver.io/api/action/setValue.html
我不知道为什么,但是如果我尝试在输入中添加单词“Testing”,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】:您的第一种方法(即onChange
触发flux 操作,更新商店并使您的表单重新呈现)似乎是一个不错的方法。我一直这样使用它,我也看到其他人也这样使用它。
关于您的以下评论:
然而,这个 onChange 回调会在用户每次输入一个字符时调用一个动作(所以它会产生很多调用,因此会重新渲染)
是的,我相信是的。我曾经创建了一个组件,其中包含许多其他组件以及一些输入字段。每当我在输入字段中键入一个字符时,整个组件(连同它包含的其他组件和输入字段)都会重新渲染,从而导致性能问题。如果我打字快,那就很明显了。您实际上可以使用https://facebook.github.io/react/docs/perf.html 进行验证。
无论如何,正如你所提到的,我是通过实现shouldComponentUpdate()
来解决这个问题的。
我想提一下的一个小技巧是创建一个自定义的<Input />
组件,该组件环绕<input />
并实现shouldComponentUpdate()
(即this.props.value !== nextProps.value || this.props.checked !== nextProps.checked
)这样,如果您创建一个表单组件,例如,有许多输入字段(使用自定义 <Input />
),只有更改的输入字段会重新呈现。
不过,我也很想看看其他人如何解决这个问题。
【讨论】:
检查我的编辑 1,使用我在 e2e 测试中遇到问题的操作方法... 为什么会导致性能问题?我认为 React 的虚拟 DOM 会在内部处理此类检查,并且只呈现已更改的内容。在性能方面,这是 React 的显着特征。我错了吗?以上是关于由 Flux Store 控制的 React Form(最佳实践?)的主要内容,如果未能解决你的问题,请参考以下文章
react--------------flux-------------劉
如何调用存储在 Store.js (React-Flux) 中的组件中的值
在 React Flux 上,我应该在哪里填充我的 Store 的初始状态?
在 ES6 中使用 Jest 测试 React Flux Store