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>
);
}
Alas, I am an idiot and passed the index into the Recipe component wrong. It should be index = { index } instead of index = { ${index} }