K
K
kirillleogky2020-06-11 11:57:57
React
kirillleogky, 2020-06-11 11:57:57

How to solve DND problem using react-beautiful-dnd?

When dragging, the last item from the list is always selected
Also, dragging still does not work properly
Used https://egghead.io/lessons/react-reorder-a-list-wi... when connecting to a project

Dumped project - mindless-produce. surge.sh
Tell me what I did wrong and how to solve the problem with the selection of the last element and the lack of drag and drop as such?


The main file in which I used DragDropContext is src/App.js :

import React, { Fragment } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import actions from "./actions";
import { DragDropContext } from 'react-beautiful-dnd';
import "./App.scss";
import Overlay from "./components/overlay/overlay";
import AddTodoInput from "./components/addTodoInput/addTodoInput";
import AddTodos from "./components/todos/todos";
import Navigation from "./components/navigation/navigation";

function App(props) {
  function filterTodos() {
    if (props.fourthData === "Done") {
      return props.thirdData.filter((item) => item.isComplete);
    } else if (props.fourthData === "Undone") {
      return props.thirdData.filter((item) => !item.isComplete);
    } else if (props.fourthData === "All") {
      return props.thirdData;
    }
  }

  function doneTodo(text) {
    const currIndex = props.thirdData.findIndex((todo) => todo.label === text);
    const oldTodo = props.thirdData[currIndex];
    const doneValue = !oldTodo.isComplete;
    const newTodoDone = { ...oldTodo, isComplete: doneValue };
    const todoStart = props.thirdData.slice(0, currIndex);
    const todoEnd = props.thirdData.slice(currIndex + 1);
    props.setThirdData([...todoStart, newTodoDone, ...todoEnd]);
  }

  function deleteTodo(text) {
    const delIndex = props.thirdData.findIndex((todo) => todo.label === text);
    const todoStart = props.thirdData.slice(0, delIndex);
    const todoEnd = props.thirdData.slice(delIndex + 1);
    props.setThirdData([...todoStart, ...todoEnd]);
  }

  function addTodo() {
    const todo = {
      label: `${props.firstData}`,
      isComplete: false,
    };
    props.setThirdData([...props.thirdData, todo]);
    props.setFirstData("");
  }
  function onDragEnd () {
    // the only one that is required
  };
  return (
    <Fragment>
      <div id="todo" className="todo_block">
        <h1 className="todo_block-title">
          To Do List
          <i id="pensil" className="todo_block-title_img"></i>
        </h1>
        <AddTodoInput onAddTodo={addTodo} />
        <DragDropContext onDragEnd={onDragEnd}>
          <AddTodos
            onDeleteTodo={deleteTodo}
            onDoneTodo={doneTodo}
            todos={filterTodos}
          />
        </DragDropContext>
        <Navigation onFilterTodos={filterTodos} />
      </div>
      <Overlay />
    </Fragment>
  );
}

App.propTypes = {
  firstData: PropTypes.string,
  thirdData: PropTypes.array,
  fourthData: PropTypes.string,
  setFirstData: PropTypes.func,
  setThirdData: PropTypes.func,
};

const mapStateToProps = (store) => {
  return {
    firstData: store.firstData.data,
    thirdData: store.thirdData.data,
    fourthData: store.fourthData.data,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    setFirstData: (data) => dispatch(actions.setFirstData(data)),
    setThirdData: (data) => dispatch(actions.setThirdData(data)),
  };
};

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


This is how my props.thirdData looks like which contains the data for the list items:
[
    { label: "Wash Kitchen", isComplete: false },
    { label: "Go To Theater", isComplete: false },
  ]


My AddTodos component which uses Droppable from react-beautiful-dnd is src/components/todos/todos.js:
import React from "react";
import PropTypes from "prop-types";
import CreateTodo from "./createTodo";
import { Droppable } from 'react-beautiful-dnd';

export default function addTodos(props) {
  return (
      <Droppable droppableId="Todos">
        {(provided) => (
          <ul
            className="todo_block-todos todos_block"
            {...provided.droppableProps}
            ref={provided.innerRef}
          >
            { props.todos().map((elem, index) => (
              <CreateTodo
                onDeleteTodo={props.onDeleteTodo}
                onDoneTodo={props.onDoneTodo}
                todo={elem}
                index={index}
                key={index}
              />
            )) }
            {provided.placeholder}
          </ul>
        )}
      </Droppable>
        );
}

addTodos.propTypes = {
  onDoneTodo: PropTypes.func,
  onDeleteTodo: PropTypes.func,
  todos: PropTypes.func,
};

props.todos() returns props.thirdData which contains data for list items

CreateTodo component which uses Draggable from react-beautiful-dnd - src/components/todos/createTodo.js :
import React from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { Draggable } from 'react-beautiful-dnd';

function createTodo(props) {
  const elem = props.todo;
  const index = props.index;
  return (
    <Draggable draggableId="draggable_todo" index={index}>
      {(provided) => (
        <li
          ref={provided.innerRef}
          {...provided.draggableProps}
          {...provided.dragHandleProps}
        >
          <span
            className={`todos_block-text ${
            elem.isComplete ? "todos_block-text_done" : ""
          }`}
            onClick={() => props.onDoneTodo(elem.label)}
          >
            {elem.label}
          </span>
          <button
            className="todos_block-trash"
            onClick={() => props.onDeleteTodo(elem.label)}
          >
            x
          </button>
        </li>
      )}
    </Draggable>
      )
};

createTodo.propTypes = {
  thirdData: PropTypes.array,
};

const mapStateToProps = (store) => {
  return {
    thirdData: store.thirdData.data,
  };
};

export default connect(mapStateToProps)(createTodo);


Project structure:
5ee1ef235ea13955885902.png

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question