Draggables grouped together on drag

560 Views Asked by At

I'm using the react-beautiful-dnd library to enable drag and drop functionality for lists, but I'm having trouble dropping the elements. Sometimes some of the draggables group together, and I can't drop anything between them. It looks like all of the index are unique. Why are the items being grouped together? Any help would be greatly appreciated.

Link to image of drag behavior

These are my render methods from the three React components used in the DragDropContext

Cookbook.js
...

render(){
    console.log("rerendering cookbook");
    let cookbook;

    // choose which cookbook to use
    if (this.state.searchbarValue === ''){
        cookbook = this.state.cookbook;
    } else {
        cookbook = this.state.filteredCookbook;
    }

    return (
        <div className="App">
            <Header />
            <div id="dialogWindow">
                {this.state.showAddChapter && <AddChapterDialog showAddChapterDialog={this.displayAddChapterWindow} rerenderCookbook={this.rerenderCookbook}/>}
                {this.state.showAddRecipe && <AddRecipeDialog showAddRecipeDialog={this.displayAddRecipeWindow} rerenderCookbook={this.rerenderCookbook}/>}
            
            </div>
            <div id="customContextWindow">
                {this.state.showContextMenu && <CustomContextMenu showContextMenu={this.displayContextMenu} renameItem={(bool) => {console.log(bool); this.displayRenameDialog(bool)}} deleteItem={this.displayDeleteDialog}/>}
            </div>
            <div id="smallDialogWindow">
                {this.state.showRename && <RenameChapterRecipeDialog showRenameChapterRecipeDialog={this.displayRenameDialog} itemTypeToModify={this.state.itemTypeToModify} textToModify={this.state.textToModify} recipeChapter={this.state.recipeChapter} rerenderCookbook={this.rerenderCookbook} />}
                {this.state.showDelete && <DeleteChapterRecipeDialog showDeleteChapterRecipeDialog={this.displayDeleteDialog} itemTypeToDelete={this.state.itemTypeToModify} textToDelete={this.state.textToModify} recipeChapter={this.state.recipeChapter} rerenderCookbook={this.rerenderCookbook} />}
            </div>
            <input type="text" id="search-bar" placeholder="Search recipes" value={this.state.searchbarValue} onChange={this.handleSearchBarChange}></input>
            <div id="cookbook">
                <DragDropContext onDragEnd={this.handleOnDragEnd}>
                { cookbook.length > 0 &&
                   <ul>
                            { cookbook.map((chapter, index) => 
                                <Chapter name={chapter.chapterName} recipes={chapter.recipes} rightClick={ (event)=>{this.showMenu(event);} } index={index}/>
                            )} 
                    
                    </ul>
                }    
                { (cookbook.length === 0 && this.state.searchbarValue !== '') &&
                   <div id="empty-search-results">No recipes found</div>
                }         
                 </DragDropContext>  

            </div>
            {!this.state.cookiesAccepted && <CookiePopupWarning accepted={this.state.cookiesAccepted} showCookiePopupWarning={(bool) => {this.showCookiePopupWarning(bool)}}/>}
            <div className="add-bar flex-container">
                <div id="add-chapter" className="add-btn" onClick={() => this.displayAddChapterWindow(true)}><div className="add-sign">+</div>Add chapter</div><div id="add-recipe" className="add-btn" onClick={()=>{ this.displayAddRecipeWindow(true) }}><div className="add-sign">+</div>Add recipe</div>
            </div>
        </div>
    );
}

Chapter.js
...

render(){
    let chapterExpanded;
    if (this.props.recipes.length === 0){  // if no recipes, don't show toggle 
        chapterExpanded="none";
    } else {  // otherwise expand chapter
        chapterExpanded="true";
    }

    return (
        <Droppable droppableId={this.props.name}>
            {(provided) => (
        <div {...provided.droppableProps} ref={provided.innerRef} className="droppable-div" >
            <li itemType="chapter" ref={this.chapterRef} chapterExpanded={chapterExpanded} onClick={()=>{this.toggleChapter();}}  onContextMenu={(event)=>{this.props.rightClick(event); event.preventDefault();}} >{this.props.name}</li>
            <ul ref={this.recipesRef} chapterOpen="true">
                {this.props.recipes.map((recipe, index) => 
                    <Recipe content={recipe} key={recipe._id} chapter={this.props.name} index={`${index}`} sendRightClick={(event)=>{this.props.rightClick(event); event.preventDefault();}}/>
                )}
            {provided.placeholder}
            </ul>
        </div>
        )}
        </Droppable>
    );
}

Recipe.js
...

render(){

    let chapter = this.props.chapter;
    let recipeId = this.props.content.nameId;

    return (
        <Draggable key={recipeId} draggableId={recipeId} index={this.props.index}>
            {(provided)=>(
                <div className='recipe' ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
                    <div>
                        <li recipeType={this.props.content.method} chapterName={chapter} link={this.recipe.recipeLink} itemType="recipe" onClick={()=>{this.displayRecipe()}} onContextMenu={(event)=>{this.props.sendRightClick(event)}}>{this.recipe.name}</li>
                        <img className="recipe-icon" src={notesImg} onClick={()=>{this.showNotes()}}/>
                    </div>
                    <textarea className="cookbook-notes" notesOpen={this.state.notesOpen} disabled={this.state.notesDisabled} value={this.state.notes} onChange={(event)=>{this.accessNotes.updateNotes(event, chapter, recipeId); this.setState({notes: event.target.value});}}></textarea>
                </div>
            )}
        </Draggable>
    );
}
1

There are 1 best solutions below

0
On BEST ANSWER

Alas, I am an idiot and passed the index into the Recipe component wrong. It should be index = { index } instead of index = { ${index} }