Реагировать — передача реквизита

В настоящее время это дает мне сообщение об ошибке, говорящее, что isCompleted не определено.

todo.isCompleted = todo.isCompleted ? ложная правда;

Приведенный выше код - это то, что вызывает ошибку.

Совет, который я получаю, заключается в том, чтобы передать реквизит todoIndex в App.js при рендеринге компонента Todo.

Не уверен, как это сделать. Любые указатели?

import React, { Component } from 'react';
import './App.css';
import ToDo from './components/ToDo.js';

class App extends Component {
 constructor(props) {
   super(props);
    this.state = {
     todos: [
       { description: 'Walk the cat', isCompleted: true },
       { description: 'Throw the dishes away', isCompleted: false },
       { description: 'Buy new dishes', isCompleted: false }],
     newTodoDescription: ''
  };
}

deleteToDo(deleteToDo) {
  console.log(this);
  let newToDos = this.state.todos.filter((todo) => {
    return todo !== deleteToDo
  } )
  this.setState({ todos: newToDos });
}

handleChange(e) {
 this.setState({ newTodoDescription: e.target.value })
}

handleSubmit(e) {
  e.preventDefault();
  if (!this.state.newTodoDescription) { return }
  const newTodo = { description: this.state.newTodoDescription, isCompleted: false };
  this.setState({ todos: [...this.state.todos, newTodo], newTodoDescription: '' });
}

toggleComplete(index) {
  const todos = this.state.todos.slice();
  const todo = todos[index];
  todo.isCompleted = todo.isCompleted ? false : true;
  this.setState({ todos: todos });
}


render() {
 return (
  <div className="App">
    <ul>
    { this.state.todos.map( (todo, index) =>
      <ToDo key={ index } description={ todo.description } isCompleted={ todo.isCompleted } toggleComplete={ this.toggleComplete.bind(this) } deleteToDo={() => this.deleteToDo(todo)} />

    )}
    </ul>
    <form onSubmit={ (e) => this.handleSubmit(e) }>
     <input type="text" value={ this.state.newTodoDescription } onChange={ (e) => this.handleChange(e) } />
     <input type="submit" />
   </form>
  </div>
);
}
}

export default App;

ToDo.js

import React, { Component } from 'react';

class ToDo extends Component {

  toggleComplete = () => {
    this.props.toggleComplete(this.props.todoIndex)
  }

  render() {

    return (

    <ul>
     <input type= "checkbox" checked= { this.props.isCompleted } 
    onChange= { this.handleToggleClick.bind(this)} />
     <span>{ this.props.description }</span>
     <button onClick={ this.props.deleteToDo }> X </button>
  </ul>

  );
 }
}
export default ToDo;

person cjl85    schedule 24.11.2018    source источник


Ответы (1)


Чтобы передать индекс компоненту ToDo, добавьте еще один реквизит:

<ToDo key={index} todoIndex={index} ... />

и убедитесь, что компонент вызывает toggleComplete с этим реквизитом индекса, т.е.

class ToDo extends React.Component {
  toggleComplete() {
    this.props.toggleComplete(this.props.todoIndex)
  }
}

Кроме того, вы изменяете объект todo в своей функции toggleComplete вместо:

todo.isCompleted = todo.isCompleted ? false : true;

Лучше сделать так:

const todos[index] = {...todo, isCompleted: !todo.isCompleted }

Или с Object.assign:

const todos[index] = Object.assign({}, todo, {isCompleted: !isCompleted})

Я думаю, что ответ Макса Курца также правильный, привязка this кажется проблематичной. Привяжите функцию toggleComplete в конструкторе или используйте функции стрелок, чтобы убедиться, что this вас не укусит.

person Stefan    schedule 24.11.2018
comment
ценю помощь. Я понимаю изменение троичного выражения, но это дает мне ошибку, говорящую, что индекс является фатальным неожиданным токеном. - person cjl85; 25.11.2018
comment
что касается вашего последнего комментария по этому поводу, вы говорите, что мне следует избегать его использования, когда это возможно, и что может быть примером использования вместо этого функции стрелки? Будет ли замена привязки this на функции со стрелками во всей программе лучшей практикой или соглашением? - person cjl85; 25.11.2018
comment
Вы можете использовать троицу, это нормально. Вы не показываете реализацию компонента ToDo, поэтому я могу только догадываться. Я предполагаю, что он вызывает функцию toggleComplete. Но этой функции нужен индекс задачи, а компонент ToDo не знает этот индекс, потому что вы не передаете его как реквизит. - person Stefan; 25.11.2018
comment
был добавлен. - person cjl85; 25.11.2018
comment
Спасибо! Итак, кажется, что вы уже передаете this.props.todoIndex в компонент ToDo, когда вызываете this.props.toggleComplete. Но вы не указываете реквизит todoIndex при рендеринге этих компонентов ToDo в компоненте приложения. В этой строке <ToDo key={ index } description={ todo.description } isCompleted={ todo.isCompleted }... /> - person Stefan; 25.11.2018
comment
так я бы изменить эту строку? - person cjl85; 25.11.2018
comment
toggleComplete={ this.toggleComplete.bind(это)} - person cjl85; 25.11.2018
comment
Здесь я скопировал ваш код в этот код и исправил ошибки codesandbox.io/s/or1lm9wpq. - person Stefan; 25.11.2018