Я не мог определить, что не так с кодом. Я передаю состояние через реквизиты, newItem прошел, но мне не удалось обновить состояние в компоненте Todos.

class AddTodo extends React.Component {
  constructor(){
    super();
    this.state = {text: ''};
  }
  onTextChanged(e){
    this.setState({text:e.target.value});
  }
  addHandler(){
    this.props.addTodo(this.state.text);
  }
  render() {
    return(
      <div>
        <input type="text" onChange={(e)=>this.onTextChanged(e)} />
        <button onClick={()=>this.addHandler()}>Add</button>
      </div>
    )
  }
}

class Todos extends React.Component {
  constructor(){
    super();
    this.state = {data: ['write book','wash clothes','jogging']};
  }
  addTodo(item){
    const newData = [...this.state.data, item]; //problem is here
    this.setState({ data: newData }); //problem is here
    console.log(this.state.data)
  }
  render() {
    return (      
      <div>
        <AddTodo addTodo={(item)=>this.addTodo(item)}/>
        <ul>
         {this.state.data.map((item)=><TodoItems key={item} item={item}/>)}
        </ul>
      </div>
    ); 
  }
}

http://jsbin.com/nitibinale/1/edit?html,js,console,output

0
Thian Kian Phin 9 Янв 2017 в 18:58

4 ответа

Лучший ответ

Ваш код верен. Это, скорее всего, ошибка в JSBin, и как она обрабатывает передачу с помощью Babel.

class AddTodo extends React.Component {
  constructor(){
    super();
    this.state = {text: ''};
  }
  onTextChanged(e){
    this.setState({text:e.target.value});
  }
  addHandler(){
    this.props.addTodo(this.state.text);
  }
  render() {
    return(
      <div>
        <input type="text" onChange={(e)=>this.onTextChanged(e)} />
        <button onClick={()=>this.addHandler()}>Add</button>
      </div>
    )
  }
}

class Todos extends React.Component {
  constructor(){
    super();
    this.state = {data: ['write book','wash clothes','jogging']};
  }
  addTodo(item){
    const newData = [...this.state.data, item]; //problem is here
    this.setState({ data: newData }); //problem is here
    console.log(this.state.data)
  }
  render() {
    return (      
      <div>
        <AddTodo addTodo={(item)=>this.addTodo(item)}/>
        <ul>
         {this.state.data.map((item)=><TodoItems key={item} item={item}/>)}
        </ul>
      </div>
    ); 
  }
}

class TodoItems extends React.Component {
  constructor(props){
    super()
    this.state = {
      text: props.item,
      isEditing: false
    };
  }
  onClickEdit(){
    this.setState({isEditing: !this.state.isEditing});
  }
  onSaveEdit(e){
    this.setState({
        isEditing: false,
        text: this.state.text
      });
  }
  onTextChanged(e){
    this.setState({text: e.target.value});
  }
  onEnter(e){
    if(e.charCode === 13){
      this.setState({
        isEditing: false,
        text: this.state.text
      });
    }
  }
  render(){ 
    return(
      <div>
      
      <li>
      {this.state.isEditing ? '' : <span>{this.state.text}</span>}

      {this.state.isEditing ? <span><input value={this.state.text} onKeyPress={(e)=>this.onEnter(e)} 
    type="text" onChange={(e)=>this.onTextChanged(e)}/></span> :''}
  &nbsp;&nbsp;
      {this.state.isEditing ? '' : <button onClick={()=>this.onClickEdit()}>Edit</button>}

      {this.state.isEditing ? <button onClick={()=>this.onSaveEdit()}>Save</button> : ''}
      </li>
      </div>
    )
  }
}

React.render(
  <Todos />,
  document.getElementById('react_example')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="react_example"></div>
1
Shubham Khatri 9 Янв 2017 в 16:56

Посмотрите на это: https://jsfiddle.net/0mhvbnhx/

class AddTodo extends React.Component {
  constructor(){
    super();
    this.state = {text: ''};
  }
  onTextChanged(e){
    this.setState({text:e.target.value});
  }
  addHandler() {
    this.props.addTodo(this.state.text);
    this.setState({ text: '' });
  }
  render() {
    return(
      <div>
        <input type="text" value={this.state.text} onChange={(e)=>this.onTextChanged(e)} />
        <button onClick={()=>this.addHandler()}>Add</button>
      </div>
    )
  }
} 

class Todos extends React.Component {
  constructor(){
    super();
    this.state = {
      data: ['write book','wash clothes','jogging']
    };
  }
  addTodo = (item) => {
    const data = [...this.state.data, item];
    this.setState({ data });
  }
  changeTodo = (i, text) => {
    const data = [...this.state.data];
    data[i] = text;
    this.setState({ data });
  }
  render() {
    return (      
      <div>
        <AddTodo addTodo={this.addTodo}/>
        <ul>
         {this.state.data.map((item, i)=>
            <TodoItems key={i} index={i} item={item} changeTodo={this.changeTodo}/>
          )}
        </ul>
      </div>
    ); 
  }
}

class TodoItems extends React.Component {
  constructor(props){
    super()
    this.state = {
      isEditing: false,
      text: '',
    };
  }
  onClickEdit(){
    this.setState({isEditing: !this.state.isEditing, text: this.props.item});
  }
  onSaveEdit(){
    this.props.changeTodo(this.props.index, this.state.text);
    this.setState({
      isEditing: false,
    });
  }
  onTextChanged(e){
    this.setState({text: e.target.value});
  }
  onEnter(e) {
    if(e.charCode === 13){
      this.onSaveEdit();
    }
  }
  render(){ 
    return(
      <div>

      <li>
      {this.state.isEditing ? '' : <span>{this.props.item}</span>}

      {this.state.isEditing ? <span><input value={this.state.text} onKeyPress={(e)=>this.onEnter(e)} 
    type="text" onChange={(e)=>this.onTextChanged(e)}/></span> :''}
  &nbsp;&nbsp;
      {this.state.isEditing ? '' : <button onClick={()=>this.onClickEdit()}>Edit</button>}

      {this.state.isEditing ? <button onClick={()=>this.onSaveEdit()}>Save</button> : ''}
      </li>
      </div>
    )
  }
}

React.render(
  <Todos />,
  document.getElementById('react_example')
);
0
Max Alekseenko 9 Янв 2017 в 16:35

Ваша проблема состоит из двух частей:

1- You forgot to set the variable in setState
2- You have a problem with your ItemTodo

Я только что исправил в вашем файле, проверьте это. http://jsbin.com/pajoliboqi/1/edit?js,console, выход

-1
damianfabian 9 Янв 2017 в 16:29

Я верю, что Шубхам прав в своем ответе. Если вы посмотрите на ответ на связанный вопрос, вы увидите, что вам, вероятно, нужно добавить {{X0} } Прагма наверху для работы JS Bin. Ваш код работает нормально.

Помимо этого: вы можете рассмотреть возможность использования версии обратного вызова setState (ссылка), потому что она асинхронная, и this.state может не всегда быть последовательным, если вы обращаетесь к ней так, как вы это делаете в настоящее время.

0
Community 23 Май 2017 в 10:30