Puru
Explore posts from serversuseDraggable how to make second argument reactive
I am building a draggable library neodrag v3, writing the solidJS adapter for it.
I want the usage to look like this:
I am expecting that when position() is updated, the entire second argument to useDraggable is recreated, and my logic can then call update cycle on it.
But that does not happen! Here is my internal code:
What could be going wrong here?
useDraggable(draggableRef, [
positionPlugin({ current: position() }),
events({
onDrag({ offset }) {
console.log(1);
setPosition({ x: offset.x, y: offset.y });
},
}),
]);
useDraggable(draggableRef, [
positionPlugin({ current: position() }),
events({
onDrag({ offset }) {
console.log(1);
setPosition({ x: offset.x, y: offset.y });
},
}),
]);
import { createDraggable } from '@neodrag/core';
import { DragEventData, unstable_definePlugin, type Plugin } from '@neodrag/core/plugins';
import { createSignal, onCleanup, onMount, createEffect, untrack } from 'solid-js';
import type { Accessor, Setter } from 'solid-js';
const draggable_factory = createDraggable();
interface DragState extends DragEventData {
isDragging: boolean;
}
const default_drag_state: DragState = {
offset: { x: 0, y: 0 },
rootNode: null as unknown as HTMLElement,
currentNode: null as unknown as HTMLElement,
isDragging: false,
};
// Create the state sync plugin with the provided setter function
const state_sync = unstable_definePlugin<[Setter<DragState>]>({
// Ommitted for brevity
});
type PluginOrFactory = Plugin | (() => Plugin);
function resolve_plugin(pluginOrFactory: PluginOrFactory): Plugin {
return typeof pluginOrFactory === 'function' ? pluginOrFactory() : pluginOrFactory;
}
export function wrapper(draggableFactory: ReturnType<typeof createDraggable>) {
return (
element: Accessor<HTMLElement | SVGElement | null | undefined>,
plugins: PluginOrFactory[] = [],
) => {
const [drag_state, set_drag_state] = createSignal<DragState>(default_drag_state);
let instance: ReturnType<typeof draggableFactory.draggable> | undefined;
const state_sync_plugin = state_sync(set_drag_state);
// Initialize draggable instance
onMount(() => {
const node = element();
if (!node) return;
// Initial plugin resolution
const resolved_plugins = untrack(() => plugins.map(resolve_plugin).concat(state_sync_plugin));
instance = draggableFactory.draggable(node, resolved_plugins);
// Cleanup on unmount
onCleanup(() => {
instance?.destroy();
});
});
// Handle plugin updates
createEffect(() => {
if (!instance) return;
// Resolve all plugins, including reactive ones
const resolved_plugins = plugins.map(resolve_plugin).concat(state_sync_plugin);
instance.update(resolved_plugins);
});
return drag_state;
};
}
export const useDraggable = wrapper(draggable_factory);
// Export necessary types and utilities
export * from '@neodrag/core/plugins';
export const instances = draggable_factory.instances;
import { createDraggable } from '@neodrag/core';
import { DragEventData, unstable_definePlugin, type Plugin } from '@neodrag/core/plugins';
import { createSignal, onCleanup, onMount, createEffect, untrack } from 'solid-js';
import type { Accessor, Setter } from 'solid-js';
const draggable_factory = createDraggable();
interface DragState extends DragEventData {
isDragging: boolean;
}
const default_drag_state: DragState = {
offset: { x: 0, y: 0 },
rootNode: null as unknown as HTMLElement,
currentNode: null as unknown as HTMLElement,
isDragging: false,
};
// Create the state sync plugin with the provided setter function
const state_sync = unstable_definePlugin<[Setter<DragState>]>({
// Ommitted for brevity
});
type PluginOrFactory = Plugin | (() => Plugin);
function resolve_plugin(pluginOrFactory: PluginOrFactory): Plugin {
return typeof pluginOrFactory === 'function' ? pluginOrFactory() : pluginOrFactory;
}
export function wrapper(draggableFactory: ReturnType<typeof createDraggable>) {
return (
element: Accessor<HTMLElement | SVGElement | null | undefined>,
plugins: PluginOrFactory[] = [],
) => {
const [drag_state, set_drag_state] = createSignal<DragState>(default_drag_state);
let instance: ReturnType<typeof draggableFactory.draggable> | undefined;
const state_sync_plugin = state_sync(set_drag_state);
// Initialize draggable instance
onMount(() => {
const node = element();
if (!node) return;
// Initial plugin resolution
const resolved_plugins = untrack(() => plugins.map(resolve_plugin).concat(state_sync_plugin));
instance = draggableFactory.draggable(node, resolved_plugins);
// Cleanup on unmount
onCleanup(() => {
instance?.destroy();
});
});
// Handle plugin updates
createEffect(() => {
if (!instance) return;
// Resolve all plugins, including reactive ones
const resolved_plugins = plugins.map(resolve_plugin).concat(state_sync_plugin);
instance.update(resolved_plugins);
});
return drag_state;
};
}
export const useDraggable = wrapper(draggable_factory);
// Export necessary types and utilities
export * from '@neodrag/core/plugins';
export const instances = draggable_factory.instances;
5 replies