使用组件对 refs 进行react

IT技术 javascript reactjs
2021-03-24 00:29:32

我有一个 React 表单,它有一个用于呈现下拉列表的组件,因为这些选项来自 API。但是,我无法访问嵌入式组件的 ref。我正在整理我的第一个表格并试图了解解决这个问题的最佳方法。

var ActivityForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();

    var noteCategoryId = this.refs.note_category_id.getDOMNode().value.trim();
    var content = this.refs.content.getDOMNode().value.trim();

    if (!category || !content) {
      return;
    }

    // this.props.onCommentSubmit({author: author, text: text});

    this.refs.note_category_id.getDOMNode().value = '';
    this.refs.content.getDOMNode().value = '';
    return;
  },
  render: function() {
    return (
      <div className="new-activity">
        <h3>New Activity</h3>
        <form onSubmit={this.handleSubmit}>
          <textarea ref='content' />
          <br />

          <label>Category</label>
          <ActivityFormCategoryDropdown /> # THE REF IN THIS COMPONENT ISN'T ACCESSIBLE
          <br />

          <input type="submit" value="Add Activity" />
        </form>
      </div>
    );
  }
});
2个回答

最好将ref视为回调属性,不再依赖于refs对象。如果您确实使用了refs对象,请避免访问refs后代组件。您应该将其refs视为私有访问器,而不是组件 API 的一部分。仅将组件实例上公开的方法视为其公共 API。

对于这种情况,我建议从提交事件中获取表单并根据需要遍历其子表单元素。添加name属性,因为这是在标准表单提交中标识表单元素的方式,然后您根本不需要refs

var ActivityForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();
    var form = e.target;

    // Use the standard [`HTMLFormElement.elements`][1] collection
    //
    // [1]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elements
    var content = form.elements['content'].value;

    // do more things with other named form elements
  },
  render: function() {
    return (
      <div className="new-activity">
        <h3>New Activity</h3>
        <form onSubmit={this.handleSubmit}>
          <textarea name='content' />
          <br />

          <label>Category</label>
          <ActivityFormCategoryDropdown />
          <br />

          <input type="submit" value="Add Activity" />
        </form>
      </div>
    );
  }
});

2016 年 9 月 21 日更新:根据字符串属性文档中的refs指导,修改建议以避免一起使用对象ref

旁注 - 这一行:var form = e.target.getDOMNode();应该是var form = e.target;
2021-05-31 00:29:32
@RossAllen ,也许你可以通知我。什么时候可以使用 refs?
2021-06-01 00:29:32
使用查询选择器的缺点,如果关注的是 refs 使用 onChange。
2021-06-02 00:29:32
@dirkdig “何时使用 refs”没有简单的答案,但通常有比通过 refs 引用组件更易于维护的方法。stackoverflow.com/a/29504636/368697是一个很好的起点,阅读 React 关于Refs 和 DOM的文档也很值得。
2021-06-07 00:29:32
@dirkdig 同意querySelector这是一个旧答案,我不确定为什么我认为这是一个好主意。
2021-06-20 00:29:32

复合组件可以有自己的引用;您可以访问它们以访问组件层次结构中更下方的引用。

例子:

但是,ssorallen 是正确的——如果可能,您应该尽量避免这种情况。相反,您应该将回调传递给孩子:

<script src="http://fb.me/react-with-addons-0.11.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.11.2.js"></script>

<div id="app"></div>

<script type="text/jsx">
/** @jsx React.DOM */

var Parent = React.createClass({
  getInitialState: function() {
    return { text: "" };
  },

  render: function() {
    return (
      <div>
        <Child onChange={this.updateText} />
        <div><button onClick={this.handleClick}>Alert Text</button></div>
      </div>
    );
  },
  
  handleClick: function() {
    alert(this.state.text);
  },

  updateText: function(text) {
    this.setState({text: text});
  }
});

var Child = React.createClass({
  render: function() {
    return <textarea onChange={this.handleChange} />;
  },

  handleChange: function(evt) {
    this.props.onChange(evt.target.value);
  }
});

React.renderComponent(<Parent />, document.getElementById("app"));
</script>

或在子进程中公开公共 API:

<script src="http://fb.me/react-with-addons-0.11.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.11.2.js"></script>

<div id="app"></div>

<script type="text/jsx">
/** @jsx React.DOM */

var Parent = React.createClass({
  render: function() {
    return (
      <div>
        <Child ref="child" />
        <div><button onClick={this.handleClick}>Alert Text</button></div>
      </div>
    );
  },
  
  handleClick: function() {
    alert(this.refs.child.getText());
  }
});

var Child = React.createClass({
  render: function() {
    return <textarea />;
  },

  getText: function() {
    return this.getDOMNode().value;
  }
});

React.renderComponent(<Parent />, document.getElementById("app"));
</script>

或使用其他一些数据流管理(例如通量、事件等)。

“托管”表单元素方法(您的最佳示例)很棒,尽管前期成本更高。
2021-06-01 00:29:32
既然ref属性的首选值是回调(请参阅ref回调属性文档),显示访问后代的示例会产生误导refs这可能会在 React 的未来版本中打破。
2021-06-03 00:29:32
嗨,我想知道哪种方式更好(我认为是第一个)以及为什么。实际上,为什么我们要避免 ref 和使用状态。我在 SO 上看到很多帖子都这么说,但我并不完全理解。谢谢你。
2021-06-22 00:29:32