在React.js表单组件中使用状态或引用?

我开始与React.js和我想要做一个简单的forms,但在documentacion我已经find了两种方法来做到这一点。 第一个是使用参考:

var CommentForm = React.createClass({ handleSubmit: function(e) { e.preventDefault(); var author = React.findDOMNode(this.refs.author).value.trim(); var text = React.findDOMNode(this.refs.text).value.trim(); if (!text || !author) { return; } // TODO: send request to the server React.findDOMNode(this.refs.author).value = ''; React.findDOMNode(this.refs.text).value = ''; return; }, render: function() { return ( <form className="commentForm" onSubmit={this.handleSubmit}> <input type="text" placeholder="Your name" ref="author" /> <input type="text" placeholder="Say something..." ref="text" /> <input type="submit" value="Post" /> </form> ); } }); 

第二个是在React组件中使用状态:

 var TodoTextInput = React.createClass({ getInitialState: function() { return { value: this.props.value || '' }; }, render: function() /*object*/ { return ( <input className={this.props.className} id={this.props.id} placeholder={this.props.placeholder} onBlur={this._save} value={this.state.value} /> ); }, _save: function() { this.props.onSave(this.state.value); this.setState({value: '' }); }); 

如果存在的话,我看不出这两种select的优缺点。 谢谢。

短版:避免参考。


它们对可维护性不利,并且失去了许多所见即所得模型渲染提供的简单性。

你有一个表格。 您需要添加一个重置表单的button。

  • 裁判:
    • 操纵DOM
    • 渲染描述了3分钟前的forms
    • 的setState
    • 渲染描述了表单的外观

input中有一个CCV编号字段,应用程序中的其他字段是数字。 现在你需要强制用户只input数字。

  • 裁判:
    • 添加一个onChange处理程序(是不是我们使用refs来避免这个?)
    • 如果不是数字,在onChange中操作dom
    • 你已经有一个onChange处理程序
    • 添加一个if语句,如果无效则什么也不做
    • 如果渲染将产生不同的结果,则只会调用渲染

呃,没关系,总理要我们做一个红色的阴影,如果它是无效的。

  • 裁判:
    • 使onChange处理程序只是调用forceUpdate什么的?
    • 使渲染输出基于…嗯?
    • 我们在哪里得到价值来validation渲染?
    • 手动操作元素的className dom属性?
    • 我迷路了
    • 重写没有参考?
    • 从dom中读取渲染,如果我们挂载否则假设有效?
  • 州:
    • 删除if语句
    • 使渲染validation基于this.state

我们需要把控制权交还给家长。 数据现在是道具,我们需要对变化做出反应。

  • 裁判:
    • 实现componentDidMount,componentWillUpdate和componentDidUpdate
    • 手动比较以前的道具
    • 用最小的变化来操纵dom
    • 嘿! 我们正在实施反应…
    • 还有更多,但我的手指受伤了
  • 州:
    • sed -e 's/this.state/this.props/' 's/handleChange/onChange/' -i form.js

人们认为裁判比保持状态更容易。 这在前20分钟可能是真实的,这之后我的经验是不正确的。 把你的自我置于一个立场,说“是的,我会在5分钟内完成”,而不是“当然,我会重写一些组件”。

我见过一些人引用上面的答案作为“永远不会使用引用”的理由,我想给我(以及其他一些React开发人员所说的)意见。

谈论使用组件实例时,“不要使用refs”情绪是正确的。 这意味着,你不应该使用refs来获取组件实例并调用它们的方法。 这是使用refs的不正确的方法,并且当refs快速向南时。

使用refs的正确(也是非常有用的)方法是当你使用它们从DOM中获得一些值的时候。 例如,如果你有一个input字段附加一个引用到那个input,那么通过引用来获取值就好了。 如果没有这种方式,你需要经过一个相当协调的过程,以保持你的input字段与当地的国家或你的通量存储 – 这似乎是不必要的。

TL; DR一般来说, refs不符合React的陈述性哲学 ,所以你应该把它们作为最后的手段。 尽可能使用state / props


为了理解在哪里使用refsstate / props ,我们来看一下React所遵循的一些devise原则。

每React 文档关于refs

避免使用refs来处理可以声明的任何事情。

每React的逃生舱devise原则

如果某些对构build应用程序有用的模式很难以声明的方式expression,我们将为其提供一个必要的API。 (他们链接到这里的参考)

这意味着React的团队build议避免refs和使用state / props来做任何可以以被动/声明方式完成的事情。

@Tyler McGinnis提供了一个非常好的答案 ,并说明了这一点

使用refs的正确(也是非常有用的)方法是当你使用它们从DOM获得一些值时…

虽然你可以做到这一点,但你会反对React的哲学。 如果你在input中有价值,那么肯定来自state / props 。 为了保持代码的一致性和可预测性,你应该坚持在那里state / props 。 我承认这样的事实,即refs有时会给你更快的解决scheme,所以如果你做了一个概念certificate, 快速和肮脏是可以接受的。

这给我们留下了几个具体的用例

pipe理焦点,文本select或媒体播放。 触发命令式animation。 与第三方DOM库集成。