Kostenitskiy_A
@Kostenitskiy_A

Как осуществить ре-рендер отображаемого массива после изменения состояния хранилища?

import React from "react";
import { connect } from "react-redux";
import { getStatuses } from "../stores/status/actions";
import { getAllTodos } from "../stores/todo/actions";
import BoardColumn from "./BoardColumn";
import "../styles/board";
import "bootstrap-icons/font/bootstrap-icons";

class Board extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isLoaded: true
    };
  }

  componentDidMount() {
    this.props.getStatuses();
    this.props.getAllTodos();
  }

  render() {
    const { isLoaded } = this.state;
    const { stauses } = this.props;

    if (isLoaded && stauses) {
      return (
        <div className="row">
          {stauses.map((status, key) => (
            <BoardColumn
              key={key}
              status={status}
            />
          ))}
        </div>
      );
    } else {
      return <div>Loading...</div>;
    }
  }
}

const mapStateToProps = (state) => {
  return {
    stauses: state.status.statuses,
  };
};

const mapDispatchToProps = {
  getStatuses,
  getAllTodos,
};

export default connect(mapStateToProps, mapDispatchToProps)(Board);


import React from "react";
import { connect } from "react-redux";
import { editTodo } from "../stores/todo/actions";
import BoardCard from "../components/BoardCard";
import "../styles/board";
import "bootstrap-icons/font/bootstrap-icons";

class BoardColumn extends React.Component {
  constructor(props) {
    super(props);

    this.onDragEnter = this.onDragEnter.bind(this);
    this.onDragOver = this.onDragOver.bind(this);
    this.onDragLeave = this.onDragLeave.bind(this);
    this.onDrop = this.onDrop.bind(this);
  }

  onDragEnter(e) {
    e.preventDefault();
  }

  onDragOver(e) {
    e.preventDefault();
  }

  onDragLeave(e) {
    e.preventDefault();
  }

  onDrop(e) {
    const id = e.dataTransfer.getData("text");
    var editedTodo = this.props.todos.find((todo) => todo.id == id);
    editedTodo.statusId = this.props.status.id;
    editedTodo.status = null;
    this.props.editTodo(editedTodo);
  }

  render() {
    const { status, todos } = this.props;

    return (
      <div className="column">
          <div className="status-title">{status.name}</div>
          <div
            className="container"
            onDragEnter={(e) => this.onDragEnter(e)}
            onDragOver={(e) => this.onDragOver(e)}
            onDragLeave={(e) => this.onDragLeave(e)}
            onDrop={(e) => this.onDrop(e)}
          >
            {todos
              .filter((todo) => todo.statusId == status.id)
              .map((todo, key) => (
                <BoardCard key={key} todo={todo} />
              ))}
          </div>
        </div>
    );
  }
}

const mapStateToProps = (state) => {
  return {
    todos: state.todo.todos,
  };
};

const mapDispatchToProps = {
  editTodo,
};

export default connect(mapStateToProps, mapDispatchToProps)(BoardColumn);


export const editTodo = (data) => {
  return async (dispatch) => {
    const responce = await fetch(EDIT_TODO_API, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    const json = await responce.json();

    dispatch({ type: EDIT_TODO, payload: json });
  };
};


Обе компоненты подключены к хранилищу из которого берут массив задач и массив статусов. При перетаскивании одной задачи в контейнер другого статуса, происходит dispatch, на сервер улетают изменения (без проблем), и изменяется локальное состояние в хранилище (без проблем), после чего компоненты должны ре-рендерится и карточка должна появиться в столбце в который мы перетащили карточку. После обновления страницы всё отображается как должно

До изменений:
62990c933eae2317559239.jpeg
62990ca11ac5b004271580.jpeg

После изменений:
62990c9c01f9f436524259.jpeg
62990ca6e90cc477764530.jpeg
62990cb01db0e133169684.jpeg

После обновления страницы:
62990c8ac7b20767297878.jpeg

P.S. Я знаю что существует библиотека react-beautiful-dnd для красивого dnd, но смысл этого pet-проекта в том, чтобы поработать со стандартными событиями
  • Вопрос задан
  • 77 просмотров
Решения вопроса 1
Kostenitskiy_A
@Kostenitskiy_A Автор вопроса
В данном случае ошибка в была в кейсе reducer'a EditTodo. В reducer'е необходимо возвращаться новое состояние, а не редактировать старое. После исправлений код выглядит так:
case EDIT_TODO: {
      const index = state.todos.findIndex((todo) => todo.id == action.payload.id);
      const newTodos = [...state.todos];
      newTodos[index] = action.payload;
      return { ...state, todos: newTodos };
}

2 строка - находим индекс редактируемого элемента
3 строка - создаём новый массив на основании предыдущего состояния
4 строка - изменяем редактируемый элемент уже нового массива
5 строка - возвращаем созданное состояние
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы