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, на сервер улетают изменения (без проблем), и изменяется локальное состояние в хранилище (без проблем), после чего компоненты должны ре-рендерится и карточка должна появиться в столбце в который мы перетащили карточку. После обновления страницы всё отображается как должно
До изменений:
После изменений:
После обновления страницы:
P.S. Я знаю что существует библиотека react-beautiful-dnd для красивого dnd, но смысл этого pet-проекта в том, чтобы поработать со стандартными событиями