@dulgeoion

Как передать значения от ребенка родителю в React?

Здравствуйте.
Такая проблема, никак не могу передать значения с формы от ребенка родителю в стейт. Использую стейт в App.js (главный компонент) и туда надо передать данные формы, которая находится в компоненте-ребенке.

Код ребенка:
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>


Код родителя:
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>
    )
  }
}


При выполнении вылетает такая ошибка
main.js:66615 Uncaught TypeError: Cannot read property 'itemInput' of undefined
    at TasksList.addItem (main.js:66615)
    at HTMLUnknownElement.boundFunc
  • Вопрос задан
  • 271 просмотр
Решения вопроса 1
rockon404
@rockon404
Frontend Developer
1. Нельзя использовать this.state в setState, так как setState асинхронный метод и на момент вызова состояние может успеть измениться. Для обновления состояния по текущему надо передавать в setState функцию возвращающую новый объект состояния. В момент вызова первым аргументом туда придет актуальное состояние компонента:
this.setState(prevState => ({
  tasks: [
    ...prevState.tasks,
    { content, comments: [], active: true},
  ],
}));

2. Хандлеры лучше биндить в конструкторе, либо использовать inline class arrow function вместо метода класса:
bind в конструкторе:
constructor(props) {
  super(props);
  this.onAddItem = this.onAddItem.bind(this);
}

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


3. С формами гораздо удобней работать через контролируемые элементы:
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>
    );
  }
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Папробуйте так

Код родителя: 
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>
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через TM ID
Похожие вопросы
YLab Тольятти
от 70 000 до 130 000 руб.
Leningrad Media Санкт-Петербург
от 60 000 руб.
18 авг. 2018, в 09:13
13000 руб./за проект
18 авг. 2018, в 01:10
17000 руб./за проект
17 авг. 2018, в 23:00
5500 руб./за проект