jQuery 如何从 React 中的子组件获取值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35800491/
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-26 17:04:30  来源:igfitidea点击:

How to get values from child components in React

jqueryajaxreactjs

提问by luke

So I am just starting to use React and am having trouble gathering the input values of inputs within a child component. Basically, I am creating different components for a large form I am making, then in the encompassing component, I want to collect all the values of inputs on the children in an object I am calling data, and then send that collected input into a POST AJAX request (you can see an example in the last component I made). I can pull the values easily enough when I am inside of the components, but pulling them from the parent component I haven't figured out.

所以我刚刚开始使用 React 并且在收集子组件中输入的输入值时遇到了问题。基本上,我正在为我正在制作的大型表单创建不同的组件,然后在包含组件中,我想收集我正在调用数据的对象中子项的所有输入值,然后将收集的输入发送到 POST AJAX 请求(您可以在我制作的最后一个组件中看到一个示例)。当我在组件内部时,我可以很容易地拉取值,但是从我还没有弄清楚的父组件拉取它们。

Thanks in advance. Just going through the pains right now with React so any recommendations on how to structure this better as well, I am all ears!

提前致谢。现在刚刚用 React 经历了痛苦,所以任何关于如何更好地构建它的建议,我都听着!

Here are my components:

这是我的组件:

Component one

组件一

var StepOne = React.createClass({
  getInitialState: function() {
    return {title: '', address: '', location: ''};
  },
  titleChange: function(e) {
    this.setState({title: e.target.value});
  },
  addressChange: function(e) {
   this.setState({address: e.target.value});
  },
  locationChange: function(e) {
    this.setState({location: e.target.value});
  },
  render: function() {
    return (
      <div className="stepOne">
        <ul>
          <li>
            <label>Title</label>
            <input type="text" value={this.state.title} onChange={this.titleChange} />
          </li>
          <li>
            <label>Address</label>
            <input type="text" value={this.state.address} onChange={this.addressChange} />
          </li>
          <li>
            <label>Location</label>
            <input id="location" type="text" value={this.state.location} onChange={this.locationChange} />
          </li>
        </ul>
      </div>
    );
  }, // render
}); // end of component

Component two

组件二

var StepTwo = React.createClass({
  getInitialState: function() {
    return {name: '', quantity: '', price: ''}
  },
  nameChange: function(e) {
    this.setState({name: e.target.value});
  },
  quantityChange: function(e) {
    this.setState({quantity: e.target.value});
  },
  priceChange: function(e) {
    this.setState({price: e.target.value});
  },
  render: function() {
    return (
      <div>
      <div className="name-section">
        <div className="add">
          <ul>
            <li>
              <label>Ticket Name</label>
              <input id="name" type="text" value={this.state.ticket_name} onChange={this.nameChange} />
            </li>
            <li>
              <label>Quantity Available</label>
              <input id="quantity" type="number" value={this.state.quantity} onChange={this.quantityChange} />
            </li>
            <li>
              <label>Price</label>
              <input id="price" type="number" value={this.state.price} onChange={this.priceChange} />
            </li>
          </ul>
        </div>
      </div>
      </div>
    );
  }
});

Final component to collect data and submit ajax request

收集数据并提交ajax请求的最终组件

EventCreation = React.createClass({
 getInitialState: function(){
  return {}
},
submit: function (e){
  var self

  e.preventDefault()
  self = this

  var data = {
    // I want to be able to collect the values into this object then send it in the ajax request. I thought this sort of thing would work below:
    title: this.state.title,
  }

  // Submit form via jQuery/AJAX
  $.ajax({
    type: 'POST',
    url: '/some/url',
    data: data
  })
  .done(function(data) {
    self.clearForm()
  })
  .fail(function(jqXhr) {
    console.log('failed to register');
  });
},
render: function() {
    return(
      <form>
        <StepOne />
        <StepTwo />
        // submit button here
      </form>
    );
  }
});

回答by Gaston Sanchez

Define methods in the child components that return the data that you want and then in the parent component when you are rendering the children, define refs so later on when you want to retrieve the data that you need you can call those method on the children.

在子组件中定义返回您想要的数据的方法,然后在渲染子组件时在父组件中定义方法,定义 refs 以便稍后当您想要检索您需要的数据时,您可以在子组件上调用这些方法。

StepOne = React.createClass({
    getData: function() {
        return this.state;
    }
});

StepTwo = React.createClass({
    getData: function() {
        return this.state;
    }
});

EventCreation = React.createClass({
    submit: function() {
        var data = Object.assign(
            {},
            this._stepOne.getData(),
            this._stepTwo.getData()
        );

        // ... do AJAX
    },

    render: function() {
        return (
            <StepOne ref={(ref) => this._stepOne = ref} />
            <StepTwo ref={(ref) => this._stepTwo = ref} />
        );
    }
});

回答by ajm

Generally speaking, you'll want to pass a function down from the parent to the children as a prop. When the children's data changes, they'll call that function as a callback.

一般来说,您需要将一个函数作为道具从父级传递给子级。当孩子的数据发生变化时,他们会将该函数作为回调调用。

This has the big advantage of letting your parent component keep track of all of the state in your application and pass down slices of state as props to its children, instead of having each component keep track of its own internal state. (That's the React approach to data flow.)

这有一个很大的优势,它可以让您的父组件跟踪应用程序中的所有状态,并将状态切片作为道具传递给它的子组件,而不是让每个组件跟踪自己的内部状态。(这是数据流的 React 方法。)

Your components might look something like this:

您的组件可能如下所示:

var StepOne = React.createClass({
  handleOnChange: function(e){
     this.props.handleChange(e.target.name, e.target.value);
  },      
  render: function() {
    return (
      <div className="stepOne">
        <ul>
          <li>
            <label>Title</label>
            <input type="text" name="title" value={this.props.title} onChange={this.handleChange} />
          </li>
          ...
        </ul>
      </div>
    );
  }, // render
}); // end of component

EventCreation = React.createClass({
 getInitialState: function(){
  return {}
},
handleChange: function(name, value){
    var tmp = {};
    tmp[name] = value;
    this.setState(tmp);
},
submit: function (e){
  var self

  e.preventDefault()
  self = this

  var data = {
    // I want to be able to collect the values into this object then send it in the ajax request. I thought this sort of thing would work below:
    title: this.state.title,
  }

  // Submit form via jQuery/AJAX
  $.ajax({
    type: 'POST',
    url: '/some/url',
    data: data
  })
  .done(function(data) {
    self.clearForm()
  })
  .fail(function(jqXhr) {
    console.log('failed to register');
  });
},
render: function() {
    return(
      <form>
        <StepOne handleChange={this.handleChange.bind(this)} title={this.state.title} .../>
        <StepTwo handleChange={this.handleChange.bind(this)} ... />
        // submit button here
      </form>
    );
  }
});

回答by Zakaria

First, you need to set some references. It will allow you to reach some DOM elements easily. Ex:

首先,您需要设置一些引用。它将允许您轻松访问某些 DOM 元素。前任:

<input id="name" type="text" value={this.state.ticket_name} onChange={this.nameChange} ref="stepOneName"/>

Then, in your submitmethod, you can get it back just like this :

然后,在您的submit方法中,您可以像这样取回它:

var data = {
name: this.refs.stepOneName.value
}

EDIT 1:You have to add a refto your components too :

编辑 1:您也ref必须在组件中添加一个:

render: function() { return( // submit button here ); } An then, access to your element :

render: function() { return( // 这里提交按钮 ); 然后,访问您的元素:

var data = {
    name: this.refs.steOneRef.refs.stepOneName.value
    }

I JSFiddled your codeant it seems ok for me.

我 JSFiddled 你的代码蚂蚁对我来说似乎没问题。

回答by Hyman

Here's a somewhat more loosely coupled solution. It depends on you setting an idfor each element. Basically what you're doing is calling the parent components onChangefunction that will get and set the data.

这是一个稍微松散耦合的解决方案。这取决于您id为每个元素设置一个。基本上,您正在做的是调用onChange将获取和设置数据的父组件函数。

var StepOne = React.createClass({
  getInitialState: function() {
    return {title: '', address: '', location: ''};
  },
  _onChange(e) {
    // set your state if needed

    // call the parent function
    this.props.onChange(
        e.target.id,
        e.target.value
    )
  },
  render: function() {
    return (
      <div className="stepOne">
        <ul>
          <li>
            <label>Title</label>
            <input id="title" type="text" value={this.state.title} onChange={this._onChange.bind(this)} />
          </li>
          <li>
            <label>Address</label>
            <input id="address" type="text" value={this.state.address} onChange={this._onChange.bind(this)} />
          </li>
          <li>
            <label>Location</label>
            <input id="location" type="text" value={this.state.location} onChange={this._onChange.bind(this)} />
          </li>
        </ul>
      </div>
    );
  }, // render
}); // end of component

var StepTwo = React.createClass({
  getInitialState: function() {
    return {name: '', quantity: '', price: ''}
  },
  _onChange(e) {
    // set your state if needed

    // call the parent function
    this.props.onChange(
        e.target.id,
        e.target.value
    )
  },
  render: function() {
    return (
      <div>
      <div className="name-section">
        <div className="add">
          <ul>
            <li>
              <label>Ticket Name</label>
              <input id="name" type="text" value={this.state.ticket_name} onChange={this._onChange.bind(this)} />
            </li>
            <li>
              <label>Quantity Available</label>
              <input id="quantity" type="number" value={this.state.quantity} onChange={this._onChange.bind(this)} />
            </li>
            <li>
              <label>Price</label>
              <input id="price" type="number" value={this.state.price} onChange={this._onChange.bind(this)} />
            </li>
          </ul>
        </div>
      </div>
      </div>
    );
  }

  EventCreation = React.createClass({
    getInitialState: function(){
      return {}
    },
    _onChange(id, value) {
      this.formData[id] = value;
    },
    submit: function (e){
      var self

      e.preventDefault()
      self = this

      // Submit form via jQuery/AJAX
      $.ajax({
        type: 'POST',
        url: '/some/url',
        data: this.formData
      })
      .done(function(data) {
        self.clearForm()
      })
      .fail(function(jqXhr) {
        console.log('failed to register');
      });
  },
  render: function() {
      return(
        <form>
          <StepOne onChange={this.onChange.bind(this)}/>
          <StepTwo onChange={this.onChange.bind(this)}/>
          // submit button here
        </form>
      );
    }
});