Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Empty listeners object returned from useSortable hook #1518

Open
ptrnln opened this issue Nov 4, 2024 · 0 comments
Open

Empty listeners object returned from useSortable hook #1518

ptrnln opened this issue Nov 4, 2024 · 0 comments

Comments

@ptrnln
Copy link

ptrnln commented Nov 4, 2024

Sorry if this is not the right place for this, but I'm not sure where else to turn to. I'm building an audio-streaming application with React and Redux.js and I want to use this library in my playlist menu component because I want touchscreen support for mobile users, and implementing such myself seems like a nightmare.

The issue

When I pause execution right after consuming from the useSortable hook in my "Item" component, I see that I get an object back for listeners, but it is entirely empty. I've made sure that all of my IDs are unique identifiers, including for the DragOverlay component, I've commented out/removed any logic that could unmount any of these components from the DOM, and I am still running into this issue. Needless to say, I am completely lost at this point.

QueueControl.jsx

export default function QueueControl () {
    const [display, setDisplay] = useState(false);
    const [activeID, setActiveID] = useState(null);
    const queue = useSelector(state => {
        return state.audio.isShuffled ?
            state.audio.queue.shuffled
            : state.audio.queue.original
    }); // An array containing the numeric IDs of tracks queued up to play
    
    // e.g. [1, 2, 3, ...]
    const currentIndex = useSelector(state => state.audio.currentIndex);

    const stateTracks = useSelector(state => state.tracks); // Object with track objects containing their metadata as values under keys corresponding to their ID

    // e.g. { 8675309: { id: 8675309, title: "867-5309/Jenny", artist: "Tommy Tutone", ... }, ... }

    const sensors = useSensors(
            useSensor(PointerSensor),
            useSensor(KeyboardSensor, {
                coordinateGetter: sortableKeyboardCoordinates,
            }),
            useSensor(MouseSensor)
        )
    

    const tracks = useMemo(() => (queue
        .slice(currentIndex + 1)
        .concat(queue.slice(0, currentIndex)))
        .map(idx => stateTracks[idx]),
    [queue, currentIndex, stateTracks]) // Array of track objects to pass to each "Item" component
     
    // e.g. [ { id: 8675309, title: "867-5309/Jenny", artist: "Tommy Tutone", ... }, ... ]

    const toggleDisplay = (e) => {
        e.preventDefault();
        setDisplay(!display);
    }

    const handlePlaylistSave = (e) => {
        e.preventDefault();
        
    }

    function handleDragStart(e) {
        const {active} = e;
        setActiveID(active.id);
    }

    function handleDragEnd (e) {
        const {active, over} = e;
        if(active.id !== over.id) {
            /* logic to reorder items */
        }
        setActiveID(null);
    }
    
    return (
        <div className="queue-control container">
            <button className="queue-control button" onClick={toggleDisplay} title="Playlist menu">
                <i className="fa-solid fa-music"/>
            </button>
            <div className={/*display ? "queue-control inner hidden" :*/ "queue-control inner"}>
                <div className="queue-control header">
                    <span>Next Up</span>
                    <button onClick={handlePlaylistSave}>Save Playlist</button>
                </div>
                <ul id="queue-list">
                    <DndContext 
                        sensors={sensors}
                        collisionDetection={closestCenter}
                        onDragStart={handleDragStart}
                        onDragEnd={handleDragEnd}
                    >
                        <SortableContext  items={tracks} strategy={verticalListSortingStrategy}>
                            {  tracks.map((track, idx) => ( 
                                    <SortableQueueItem key={idx} track={track} id={track.id}/>
                                ))
                            }
                        </SortableContext>
                        <DragOverlay>
                            { activeID ? 
                                <QueueItem track={tracks[activeID]} id={'overlay'}/>
                                : null
                            }
                        </DragOverlay>
                    </DndContext>
                </ul>
            </div>
        </div>
    ) 
}

SortableQueueItem.jsx

export default function SortableQueueItem(props) {
    const { 
        attributes, 
        listeners, 
        setNodeRef,
        transform,
        transition 
    } = useSortable({id: props.id});

    
    const style = {
        transform: CSS.Transform.toString(transform),
        transition,
    };

    return (
        <QueueItem 
            id={props.id}
            ref={setNodeRef} 
            {...props} 
            {...attributes} 
            style={style} 
            listeners={listeners} />
    )
}

QueueItem.jsx

import { forwardRef } from "react";

const QueueItem = forwardRef(({track, listeners, ...props}, ref) => {
    return (
        <div className="queue-item" ref={ref} {...props}>
            <div className="handle" {...listeners}>
                <i className="fa-solid fa-grip-vertical"></i>
            </div>
            <span className="title">{track.title}</span> 
            <span className="artist"> {track.artist.username}</span>
        </div>
    )
});
export default QueueItem 

And this is what is returned from the useSortable hook for listeners:
Screenshot 2024-11-04 161501

Any help would be greatly appreciated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant