React.js如何访问子组件中的输入值

时间:2016-12-24 22:39:09

标签: javascript reactjs ecmascript-6

我编写了简单的待办事项应用程序,但现在我在App(InputForm)的子组件中访问输入值时遇到了麻烦。

也许我需要以某种方式重建结构或逻辑以使其有效?

这是我的App组件:

class App extends React.Component {
  constructor (){
      super();
      this.state = {
          items : []
      }
  }

  addTodo ( e ){
    e.preventDefault();

    let itemHeading = this.refs.todoInput.value; // TODO Access to input value
    let itemKey = Date.now();

    const items = this.state.items.slice();

    items.push({
      heading: itemHeading,
      key: itemKey
    })

    this.setState({items: items});
  }
  render() {
    return (
      <div className="app-container">
        <InputForm onSubmit={this.addTodo.bind(this)}></InputForm>
        <TodoItems entries={this.state.items} />
      </div>
    );
  }
}

这是我的InputForm组件:

class InputForm extends React.Component {
  render (){
    return (
      <form onSubmit={this.props.onSubmit}>
        <input
          ref="todoInput"
          type="text"
          placeholder="Type your text here" />
        <button type="submit">Add to list</button>
      </form>
    )
  }
}

感谢您的帮助。

3 个答案:

答案 0 :(得分:10)

input转换为controlled component,并在输入中的文本发生更改时更新状态。单击提交时,将值发送给处理程序。

删除refs,因为它们应该用于需要直接访问DOM的内容。这就是文档对refs所说的反应:

  

在典型的React数据流中,道具是唯一的父级   组件与他们的孩子互动。要修改孩子,你   用新道具重新渲染它。但是,有几种情况你   需要在典型的数据流之外强制修改一个孩子。   要修改的子项可以是React组件的实例,或者   它可能是一个DOM元素。对于这两种情况,React提供了一个   逃生舱

这是一个不需要这个逃生舱口的情况,你应该只使用道具。

带评论的工作演示:

const TodoItems = ({ entries }) => (
  <ul>
    {entries.map(({ heading, key }) => (
      <li key={key}>{heading}</li>
    ))}
  </ul>
);

class App extends React.Component {
  state = {
    items : []
  }

  // addTodo will receive the needed value without refs
  addTodo = (heading) => heading !== '' && this.setState(({ items }) => ({
    items: items.concat({ // concat returns a new array
      heading,
      key: Date.now()
    })
  }));

  render() {
    return (
      <div className="app-container">
        <InputForm onSubmit={this.addTodo}></InputForm>
        <TodoItems entries={this.state.items} />
      </div>
    );
  }
}

class InputForm extends React.Component {
  state = {
    input: ''
  };

  // input change handler
  onInput = (e) => this.setState({
    input: e.target.value
  });

  // submit handler
  onSubmit = (e) => {
    e.preventDefault();
    this.props.onSubmit(this.state.input);
  }

  render (){
    return (
      <form onSubmit={this.onSubmit}>
        <input
          // use value and onChange so it will be a controlled component
          value={ this.state.value }
          onChange={ this.onInput }
          type="text"
          placeholder="Type your text here" />
        <button type="submit">Add to list</button>
      </form>
    )
  }
}

ReactDOM.render(
  <App />,
  demo
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="demo"></div>

答案 1 :(得分:1)

您尝试访问的引用对象位于InputForm实例上,因此如果您想从App访问该实例,则必须在InputForm也是如此。 然后,您可以使用this.refs.InputForm.refs.todoInput访问它。

话虽如此,最好做ref refback而不是ref string,因为ref字符串计划从React中删除。 另外,最好不要过度使用refs。也许您可以通过onChange事件左右保存父状态中的值。

https://facebook.github.io/react/docs/refs-and-the-dom.html#the-ref-callback-attribute

答案 2 :(得分:1)

通过将父对象从父组件传递到子组件并直接从子组件访问父组件的方法,我将为您提供最简单的解决方案:

class App extends React.Component {
  constructor (){
      super();
      this.state = {
          items : []
      }
  }

  addTodo ( value ){

    let itemHeading = value; 
    let itemKey = Date.now();

    const items = this.state.items.slice();

    items.push({
      heading: itemHeading,
      key: itemKey
    })

    this.setState({items: items});
  }
  render() {
    return (
      <div className="app-container">
        <InputForm parentObject={this}></InputForm>
        <TodoItems entries={this.state.items} />
      </div>
    );
  }
}

class InputForm extends React.Component {

this.onSubmit = this.onSubmit.bind(this);
this.onInput = this.onInput.bind(this);


 onSubmit()
 {
  //invoking parent component function directly by passing parameter to it. 
  this.props.parentObject.addTodo(this.state.value);
 }

onInput(e) {
    this.setState({
      input: e.target.value
    });
  }

  render (){
    return (
      <form onSubmit={this.props.onSubmit}>
        <input
          value={ this.state.value }
          onChange={ this.onInput }
          ref="todoInput"
          type="text"
          placeholder="Type your text here" />
        <button type="submit">Add to list</button>
      </form>
    )
  }
}