admin管理员组

文章数量:1200394

I wrote simple todo app, but now I have troubles with accessing to value of input in child component for App (InputForm).

Maybe I need to rebuild structure or logic somehow to make it works ?

Here's my App component:

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>
    );
  }
}

Here's my InputForm component:

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>
    )
  }
}

Thanks for help.

I wrote simple todo app, but now I have troubles with accessing to value of input in child component for App (InputForm).

Maybe I need to rebuild structure or logic somehow to make it works ?

Here's my App component:

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>
    );
  }
}

Here's my InputForm component:

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>
    )
  }
}

Thanks for help.

Share Improve this question asked Dec 24, 2016 at 22:39 Alexander SeredenkoAlexander Seredenko 8193 gold badges11 silver badges26 bronze badges 3
  • you want to pass the value to which component from which component.? – Codesingh Commented Dec 24, 2016 at 22:48
  • @Codesingh I want to pass value of input from InputForm and use it in addTodo function in App component. You can see TODO comment on line where I need it. – Alexander Seredenko Commented Dec 24, 2016 at 22:51
  • Possible duplicate of How to get values from child components in React – Jim G. Commented Jul 11, 2018 at 0:33
Add a comment  | 

3 Answers 3

Reset to default 15

Convert the input to a controlled component, and update the state whenever the text in the input changes. When submit is clicked, send the value to the handler.

Remove the refs, as they should be used for stuff that requires direct access to the DOM. This is what react docs has to say about refs:

In the typical React dataflow, props are the only way that parent components interact with their children. To modify a child, you re-render it with new props. However, there are a few cases where you need to imperatively modify a child outside of the typical dataflow. The child to be modified could be an instance of a React component, or it could be a DOM element. For both of these cases, React provides an escape hatch.

This is a case that doesn't requires this escape hatch, and you should just use props.

Working demo with comments:

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>

The refs object you're trying to access is on the InputForm instance, so if you want to access that instance from App you'll have to add a ref on the InputForm as well. Then you can access it with this.refs.InputForm.refs.todoInput.

Having said that, it's best to do ref callbacks rather than ref string, as the ref string is planned to be removed from React. Also it is best advised not to over-use refs. Maybe you can hold the value in the parent's state via onChange event or so.

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

I will give you the easiest solution by passing parent object from parent component to child component and accessing methods of parent component directly from the child component:

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>
    )
  }
}

本文标签: javascriptReactjs How to access to input value in child componentStack Overflow