Javascript 使用组件对 refs 进行反应

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25941585/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:07:12  来源:igfitidea点击:

React refs with components

javascriptreactjs

提问by brandonhilkert

I have React form that has a Component used to render a drop down because the options are coming from an API. However, I can't access the ref for the embedded component. I'm putting together my first form and trying to understand the best way to approach this.

我有一个 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>
    );
  }
});

回答by Ross Allen

It is preferred to treat the refas a callback attributeand no longer depend on the refsObject. If you do use the refsObject, avoid accessing refsof descendant components. You should treat refsas a private accessor and not part of a component's API. Treat only the methods exposed on a component instance as its public API.

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

For this case, I suggest grabbing the form from the submit event and traversing its child form elements as needed. Add nameattributes since that's how form elements are identified in standard form submissions, and then you shouldn't need refsat all:

对于这种情况,我建议从提交事件中获取表单并根据需要遍历其子表单元素。添加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>
    );
  }
});

Update 2016-09-21: Revise suggestion to avoid the refsObject all together per guidance from the refString Attributedocs.

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

回答by Michelle Tilley

Composite components can have their own refs; you can reach in to them to access the refs further down the component hierarchy.

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

Example:

例子:

<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.refs.textarea.getDOMNode().value);
  }
});

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

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

However, ssorallen is correct—you should try to avoid this if possible. Instead, you should either pass callbacks into children:

但是,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>

or expose a public API in the child:

或在子进程中公开公共 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>

or use some other data flow management (e.g. flux, events, etc).

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