Skip to content

Commit

Permalink
Fix resize observer not always being connected
Browse files Browse the repository at this point in the history
  • Loading branch information
clauderic committed Jan 8, 2022
1 parent 528c67e commit 7833da4
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .changeset/droppable-resize-observer.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface ResizeObserverConfig {
}
```

By default, only the current droppable is re-measured when a resize event is observed. However, this may not be suitable for all use-cases. When an element resizes, it can affect the layout and position of other elements, such that it may be necessary to re-measure other droppable nodes in response to that single resize event. The `recomputeIds` property can be used to specify which droppable `id`s should be re-measured in response to resize events being observed.
By default, only the current droppable is scheduled to be re-measured when a resize event is observed. However, this may not be suitable for all use-cases. When an element resizes, it can affect the layout and position of other elements, such that it may be necessary to re-measure other droppable nodes in response to that single resize event. The `recomputeIds` property can be used to specify which droppable `id`s should be re-measured in response to resize events being observed.

For example, the `useSortable` preset re-computes the measurements of all sortable elements after the element that resizes, so long as they are within the same `SortableContext` as the element that resizes, since it's highly likely that their layout will also shift.

Expand Down
3 changes: 2 additions & 1 deletion .changeset/use-node-ref.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
'@dnd-kit/utilities': patch
---

The `useNodeRef` hook's `onChange` argument now receives both the current node and the previous node that were attached to the ref.
- The `useNodeRef` hook's `onChange` argument now receives both the current node and the previous node that were attached to the ref.
- The `onChange` argument is only called if the previous node differs from the current node
12 changes: 11 additions & 1 deletion packages/core/src/hooks/useDroppable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export interface UseDroppableArguments {
const ID_PREFIX = 'Droppable';

const defaultResizeObserverConfig = {
timeout: 50,
timeout: 25,
};

export function useDroppable({
Expand Down Expand Up @@ -110,6 +110,16 @@ export function useDroppable({
const [nodeRef, setNodeRef] = useNodeRef(handleNodeChange);
const dataRef = useLatestValue(data);

useEffect(() => {
if (!resizeObserver || !nodeRef.current) {
return;
}

resizeObserver.disconnect();
resizeObserverConnected.current = false;
resizeObserver.observe(nodeRef.current);
}, [nodeRef, resizeObserver]);

useIsomorphicLayoutEffect(
() => {
dispatch({
Expand Down
11 changes: 9 additions & 2 deletions packages/utilities/src/hooks/useNodeRef.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import {useRef, useCallback} from 'react';

import {useLatestValue} from './useLatestValue';

export function useNodeRef(
onChange?: (
newElement: HTMLElement | null,
previousElement: HTMLElement | null
) => void
) {
const onChangeRef = useLatestValue(onChange);
const node = useRef<HTMLElement | null>(null);
const setNodeRef = useCallback(
(element: HTMLElement | null) => {
onChange?.(element, node.current);
if (element !== node.current) {
onChangeRef.current?.(element, node.current);
}

node.current = element;
},
[onChange]
//eslint-disable-next-line
[]
);

return [node, setNodeRef] as const;
Expand Down

0 comments on commit 7833da4

Please sign in to comment.