Обновление списка отображаемых компонентов при удалении в React - PullRequest
0 голосов
/ 16 марта 2019

В начале моего пути с React я создаю простое приложение, в котором пользователь может добавлять / удалять задачи, которые в основном являются отдельными компонентами.

Я создаю задачи, используя:

addTask(taskObj){
    let tasksList = this.state.tasksList;
    tasksList.push(taskObj);
    this.setState({tasksList : tasksList});
}

Отображаю список компонентов (задач) следующим способом:

showTasks(){
    return (
        this.state.tasksList.map((item, index) => {
            return <SingleTask
                taskObj={item}
                removeTask = {(id) => this.removeTask(id)}
                key = {index}/>;
        })
    );
}

метод удаления конкретной задачи принимает уникальный идентификатор задачи в качестве аргумента и на основании этого идентификатора я удаляю его из списка задач:

removeTask(uID){
  this.setState(prevState => ({
        tasksList: prevState.tasksList.filter(el => el.id != uID )
    }));
}

Но проблема в том, что когда я удаляю любой элемент, кроме последнего, создается впечатление, что фактический список компонентов такой же, только разные объекты передаются этим компонентам.

Например: Давайте представим, что у меня есть 2 созданных компонента, если я установлю state.Name = 'Foo' на первом и state.Name = 'Bar' на втором. Если я нажимаю на кнопку «Удалить» на первом объекте, объект, связанный с этим компонентом, удаляется, второй становится первым, но это состояние. Имя теперь «Foo» вместо «Bar».

Я думаю, что мне чего-то не хватает с правильным созданием / удалением / отображением компонентов в реакции.

Edit:

Метод, используемый для удаления выбранного компонента:

removeCurrentTask(){
    this.props.removeTask(this.props.taskObj.id);
}

Компонент SingleTask:

class SingleTask extends Component{
constructor(props) {
    super(props);

    this.state={
        showMenu : false,
        afterInit : false,
        id: Math.random()*100
    }

    this.toggleMenu = this.toggleMenu.bind(this);
}

toggleMenu(){
    this.setState({showMenu : !this.state.showMenu, afterInit : true});
}

render(){
    return(
        <MDBRow>
            <MDBCard className="singleTaskContainer">

                <MDBCardTitle>
                    <div class="priorityBadge">

                    </div>
                </MDBCardTitle>
                <MDBCardBody className="singleTaskBody">
                    <div className="singleTaskMenuContainer">

                        <a href="#" onClick={this.toggleMenu}>
                            <i className="align-middle material-icons">menu</i>
                        </a>
                        <div className={classNames('singleTaskMenuButtonsContainer animated',
                            {'show fadeInRight' : this.state.showMenu},
                            {'hideElement' : !this.state.showMenu},
                            {'fadeOutLeft' : !this.state.showMenu && this.state.afterInit})}>
                            <a
                                title="Remove task"
                                onClick={this.props.removeTask.bind(null, this.props.taskObj.id)}
                                className={
                                    classNames(
                                        'float-right btn-floating btn-smallx waves-effect waves-light listMenuBtn lightRed'
                                        )
                                }
                            >
                                <i className="align-middle material-icons">remove</i>
                            </a>
                            <a  title="Edit title"
                                className={classNames('show float-right btn-floating btn-smallx waves-effect waves-light listMenuBtn lightBlue')}
                            >
                                <i className="align-middle material-icons">edit</i>
                            </a>
                        </div>
                    </div>
                    {this.props.taskObj.description}
                    <br/>
                    {this.state.id}
                    </MDBCardBody>
            </MDBCard>
        </MDBRow>
    );
}

}

Ниже визуального представления ошибки, изображение слева - до удаления, а справа - после удаления. Хотя карта с «22» была удалена, сам компонент не был удален, ему был передан только другой объект.

enter image description here

Ответы [ 2 ]

0 голосов
/ 20 марта 2019

Просто чтобы уточнить, решение оказалось проще, чем ожидалось.

В

const showTasks = () =>  taskList.map((item, index) => (
        <SingleTask
            taskObj={item}
            removeTask ={removeTask}
            key = {item.id}
        />
        )
    )

Я передавал карту index в качестве ключа, когда я изменил ее на {item.id} все работает как положено.

0 голосов
/ 16 марта 2019

Короче говоря, в утверждении tasksList.push(<SingleTask taskObj={taskObj} removeTask ={this.removeTask}/>);, removeTask = {this.removeTask} должно стать removeTask = {() => this.removeTask(taskObj.id)}.

Однако я бы пересмотрел способ addTask и showTasksнаписаны.Хотя то, как вы написали, не является неправильным, это семантически несостоятельно.Вот что я бы сделал:

addTask(taskObj){
    let tasksList = this.state.tasksList;
    tasksList.push(taskObj);
    this.setState({tasksList : tasksList});
}

showTasks(){
    return (
        this.state.tasksList.map((item, index) => {
            return <SingleTask
                       taskObj={item}
                       removeTask ={() => this.removeTask(item.id)}/>;
        })
    );
}

const SingleTask = (task) => {
  const { taskObj } = task;
  return <div onClick={task.removeTask}>
    { taskObj.title }
  </div>
}

// Example class component
class App extends React.Component {
state = {
    tasksList: [
      { id: 1, title: "One" },
      { id: 2, title: "Two" },
      { id: 3, title: "Three" },
      { id: 4, title: "Four" }
    ]
  }
  
  addTask = (taskObj) => {
    let tasksList = this.state.tasksList;
    tasksList.push(taskObj);
    this.setState({tasksList : tasksList});
  }
  
  showTasks = () => {
    return (
        this.state.tasksList.map((item, index) => {
          return <SingleTask
            key={index}
            taskObj={item}
            removeTask ={() => this.removeTask(item.id)}/>;
        })
    );
  }
  
  removeTask(id) {
    this.setState(prevState => ({
      tasksList: prevState.tasksList.filter(el => el.id != id )
    }));
  }
  
  render() {
    return (
      <div className="App">
        <div> {this.showTasks()} </div>
      </div>
    );
  }
}

// Render it
ReactDOM.render(
  <App />,
  document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
...