D
D
dulgeoion2018-02-17 13:11:48
React
dulgeoion, 2018-02-17 13:11:48

How to pass values ​​from child to parent in React?

Hello.
Such a problem, I can’t transfer the values ​​\u200b\u200bfrom the form from the child to the parent in the state. I use a state in App.js (the main component) and I need to pass the form data there, which is in the child component.
Child code:

class TasksList extends React.Component {


  addItem(event){
    event.preventDefault();
    console.log(event.refs.itemInput.value);
    let input = event.refs.itemInput.value;
    this.props.onAddItem(input);
  }

  render(){
    return(
      <div className="col-sm-5 col-xs-12">
        <h2> Items </h2>
        <form className="form-inline" onSubmit={this.addItem.bind(this)}>
            <input type="text" ref="itemInput" placeholder="Type name here..." className="form-control" />
            <input type="submit" ref='itemSubmit' value="Add new" className="btn btn-info" />

        </form  >
</div>

Parent code:
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      tasks: [{
        active: true,
        content: "Eat chicken",
        comments: ["comment1", "comment2"]
        }
      ]
    };
  }

  onAddItem(content){
    this.setState({
      tasks: this.state.tasks.concat.push(content: content, comments: [], active: true)
    });
  }

  render(){
    return(
      <div className="container-fluid" >
        <div className="row app-row">
          <LogoBar />
          <TasksList tasks = {this.state.tasks} addItem={this.onAddItem.bind(this)} />
        </div>
      </div>
    )
  }
}

When executing, it throws this error
main.js:66615 Uncaught TypeError: Cannot read property 'itemInput' of undefined
    at TasksList.addItem (main.js:66615)
    at HTMLUnknownElement.boundFunc

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Anton Spirin, 2018-02-17
@dulgeoion

1. You cannot use this.state in setState , since setState is an asynchronous method and the state may have time to change at the time of the call. To update the state according to the current one, it is necessary to pass to setState a function that returns a new state object. At the time of the call, the current state of the component will come there as the first argument:

this.setState(prevState => ({
  tasks: [
    ...prevState.tasks,
    { content, comments: [], active: true},
  ],
}));

2. It is better to bind handlers in the constructor, or use the inline class arrow function instead of the class method:
bind in the constructor:
constructor(props) {
  super(props);
  this.onAddItem = this.onAddItem.bind(this);
}

inline class arrow function :
onAddItem = content => {
  // some stuff
};

3. It is much more convenient to work with forms through controlled elements:
class Example extends Component {
  state = {
    inputValue: '',
  };

  handleChange = e => { 
    const { name, value } = e.target;
    
    this.setState({
      [name]: value,
    });
  };

  render() {
    const { inputValue } = this.state;

    return (
      <Wrapper>
        <input
          name="inputValue"
          value={inputValue}
          onChange={this.handleChange}
        />
        ...
      </Wrapper>
    );
  }

R
Roman Aleksandrovich, 2018-02-17
@RomReed

Try this

Код родителя: 
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      tasks: [{
        active: true,
        content: "Eat chicken",
        comments: ["comment1", "comment2"]
        }
      ]
    };
  }

needData(data){
   console.log("data",data)
}

  onAddItem(content){
    this.setState({
      tasks: this.state.tasks.concat.push(content: content, comments: [], active: true)
    });
  }

  render(){
    return(
      <div className="container-fluid" >
        <div className="row app-row">
          <LogoBar />
          <TasksList tasks = {this.state.tasks} addItem={this.onAddItem.bind(this)}  needData={()=>this.needData}/>
        </div>
      </div>
    )
  }
}

Код ребенка: 
class TasksList extends React.Component {


  addItem(event){
    event.preventDefault();
    console.log(event.refs.itemInput.value);
    let input = event.refs.itemInput.value;
    this.props.onAddItem(input);
    this.props.needData(input)
  }

  render(){
    return(
      <div className="col-sm-5 col-xs-12">
        <h2> Items </h2>
        <form className="form-inline" onSubmit={this.addItem.bind(this)}>
            <input type="text" ref="itemInput" placeholder="Type name here..." className="form-control" />
            <input type="submit" ref='itemSubmit' value="Add new" className="btn btn-info" />

        </form  >
</div>

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question