reactjsreact-beautiful-dndreorderlist

React Beautiful DND not working, element is not draggable


I've been trying to implement my Reordering list inside my card using react-beautiful-dnd library but I tried everything in a similar way from egghead.io courses but could not get it working. Here's my code:

    import React, { Component } from "react";
import { Card, Badge } from "react-bootstrap";
import "./projects.scss";
import projectInfo1 from "../../jsonData/projects1";
import { IconContext } from "react-icons";
import { FiPlus } from "react-icons/fi";
import { Droppable, DragDropContext, Draggable } from "react-beautiful-dnd";

class Projects extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.onDragEnd = this.onDragEnd.bind(this);
    this.onDragStart = this.onDragStart.bind(this);
  }
  onDragEnd = result => {};
  onDragStart = result => {};

  render() {
    return (
      <div className="projectCards">
        {projectInfo1.projectsOrder.map((projectID) => {
          const project = projectInfo1.projects[projectID];
          return (
            <DragDropContext onDragEnd={this.onDragEnd} onDragStart={this.onDragStart}>
            <Card className="projectCard" bg="light" style={{ width: "21rem" }} key={project.id}>
                <Card.Header color="#366FF0" className="projectcardheader">
                  {project.projectName}
                </Card.Header>
                <Droppable droppableId={project.id}>
                  {(provided) => (
                    <div
                      className="cardcontent"
                      innerRef={provided.innerRef}
                      {...provided.droppableProps}
                    >
                      {project.topics.map((j, index) => {
                        return (
                          <Draggable draggableId={j.id} index={index}>
                            {(provided) => (
                              <Card
                                key={j.id}
                                className="topicscard"
                                {...provided.draggableProps}
                                {...provided.dragHandleProps}
                                innerRef={provided.innerRef}
                              >
                                <Card.Title className="topicsheading">
                                  {j.topicName}
                                </Card.Title>
                                <Card.Text className="topicdescription">
                                  {j.topicDescription}
                                </Card.Text>
                                <div>
                                  {j.topicTags ? (
                                    j.topicTags.map((k) => {
                                      return (
                                        <Badge
                                          variant="primary"
                                          className="tags"
                                        >
                                          {k}
                                        </Badge>
                                      );
                                    })
                                  ) : (
                                    <Badge variant="primary"></Badge>
                                  )}
                                </div>
                              </Card>
                            )}

                          </Draggable>
                        );
                      })}
                      {provided.placeholder}
                    </div>
                  )}
                </Droppable>
                <div className="addnewcard">
                  <IconContext.Provider
                    value={{
                      style: { verticalAlign: "middle" },
                      className: "reacticon",
                    }}
                  >
                    <FiPlus />
                  </IconContext.Provider>{" "}
                  Add another discussion
                </div>
            </Card>
            </DragDropContext>
          );
        })}
      </div>
    );
  }
}
export default Projects;

Also I'm attaching a photo, its just showing drag cursor on hovering over the card, but nothing happens on drag, any help will save me!

const projectsInfo1 = {

    projectsOrder:['Project-2','Project-1','Project-5','Project-4','Project-3'],
    projects: {
      'Project-1':{
        projectName: "Project 1",
        id:"p1",
        topics:[{
            id:"p1t1",
            topicName: "Adding a feature: GSoC1",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content.",      
            topicTags:['ReactJs','NodeJS']
        },
        {   id:'p1t2',
            topicName: "Adding a feature: GSoC2",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content.",
            topicTags:['ReactJs','NodeJS']     
        },
        {   id:'p1t3',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content.",
            topicTags:['ReactJs','NodeJS']      
        },
        {   id: 'p1t4',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content.",
            topicTags:['ReactJs','NodeJS']      
        }],
      },
      'Project-2':{
        projectName: "Project 2",
        id:'p2',
        topics:[{
            id:'p2t1',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        },
        {   id:'p2t2',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        },
        {   id:'p2t3',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        },
        {   id:'p2t4',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        }],
      },
      'Project-3':{
        projectName: "Project 3",
        id:'p3',
        topics:[{
            id:'p3t1',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        },
        {   id:'p3t2',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        },
        {   id:'p3t3',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        },
        {   id:'p3t4',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        }],
      },
      'Project-4':{
        projectName: "Project 4",
        id:'p4',
        topics:[{
            id:'p4t1',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        },
        {   id:'p4t2',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        },
        {   id:'p4t3',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        },
        {   id:'p4t4',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        }],
      },
      'Project-5':{
        projectName: "Project 5",
        id:'p5',
        topics:[{
            id:'p5t1',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        },
        {   id:'p5t2',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        },
        {   id:'p5t3',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        },
        {   id:'p5t4',
            topicName: "Adding a feature: GSoC",
            topicDescription: "Some quick example text to build on the card title and make up the bulk of the card's content."      
        }],
      },
    },
  };

  export default projectsInfo1;

Solution

  • NOTE :

    After the conversation in comment , issue was with innerRef

    <div innerRef={provided.innerRef} to <div ref={provided.innerRef}

    In demo they were using styled component so they are using innerRef, but if you are using simple div then you should use just ref


    Issue :

    1) it won't work automatically, you need to write code for it on drag end event onDragEnd

    2) There is no state management, so even if you make changes on your imported json, it wont be reflected as react have no idea to re-render the dom again.


    Solution :

    1) Maintain your imported data in state

    2) Write some code inside the onDragEnd, check all conditions over there and apply changes on your state accordingly ( Don't mutate the state or it will not reflect the changes )

    Note : Below is just code snippet of demo from egghead.io for sorting listing within same droppable area , just give overall idea how it should be

    onDragEnd = result => {
      const { destination, source, draggableId } = result
    
      if (!destination) {
        return
      }
    
      if (
        destination.droppableId === source.droppableId &&
        destination.index === source.index
      ) {
        return
      }
    
      const start = this.state.columns[source.droppableId]
      const finish = this.state.columns[destination.droppableId]
    
    
      // this is the logic behind sorting state , you have to do it by your self
      if (start === finish) {
        const newTaskIds = Array.from(start.taskIds)
        newTaskIds.splice(source.index, 1)
        newTaskIds.splice(destination.index, 0, draggableId)
    
        const newColumn = {
          ...start,
          taskIds: newTaskIds
        }
    
        const newState = {
          ...this.state,
          columns: {
            ...this.state.columns,
            [newColumn.id]: newColumn
          }
        }
    
        this.setState(newState)
        return
      }
    }
    

    WORKING DEMO :

    Edit react-beautiful-dnd tutorial