Reordenar elementos con utilizando Drag & Drop

npm i react-beautiful-dnd

En el useEffect llamaremos al método que devolverá los datos ordenados en función de la propiedad order:

const getObras = (userId) => getObrasFromUser(userId).then((data) =>  setObras(data.sort(compare)));
<DragDropContext onDragEnd={onDragEnd}>
          <Droppable droppableId="boxes" direction="horizontal">
            {(provided) => (
              <div className="boxes" {...provided.droppableProps} ref={provided.innerRef}>
                {
                  items.map((item, index) => <Draggable key={item.id} index={index} draggableId={item.id}>{(provided) => (<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>{item.txt}</div>)}</Draggable>)
                }
              </div>)}
          </Droppable>
</DragDropContext>

Cuando soltemos el elemento que estamos desplazando, debemos gestionar su nueva posición

const onDragEnd = (result) => {
    if (!result.destination) {
      return;
    }

    const itms= reorder(
      obras,
      result.source.index,
      result.destination.index
    );

    setItems(itms) // Esto actualiza el estado de los items para que se pinten reordenados en pantalla
    updateItems(items); //Esto actualiza el valor en firebase 
}
export const reorder = (list, startIndex, endIndex) => {
    const result = Array.from(list); const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);
    return result.map((data, index) => ({ ...data, order: index }));
};

En la base de datos nuestros items tendrán una propiedad order cuyo valor debemos actualizar en función de la nueva posición de los elementos:

export const updateItems = async (items) => {
    const batch = writeBatch(db)
    const subColRef = collection(db, 'items');

    items.forEach(({ id, ...data }, i) => {
        batch.update(doc(subColRef, id), { ...data, order: i });
    });

    return batch.commit();
}
← Login con Auth0
Next JS →