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

Update simplified DnD handler api and memoize useDnDHooks #3533

Merged
merged 19 commits into from
Sep 22, 2022

Conversation

LFDanLu
Copy link
Member

@LFDanLu LFDanLu commented Sep 19, 2022

Followup review items from #3266

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

🧢 Your Project:

RSP

@LFDanLu LFDanLu changed the title Update simplified DnD handler api and memoize useDnDHooks return (WIP) Update simplified DnD handler api and memoize useDnDHooks return Sep 19, 2022
@LFDanLu LFDanLu changed the title (WIP) Update simplified DnD handler api and memoize useDnDHooks return (WIP) Update simplified DnD handler api and memoize useDnDHooks Sep 19, 2022
let {draggingCollectionRef, draggingKeys} = globalDndState;
let isInternalDrop = draggingCollectionRef?.current != null && draggingCollectionRef?.current === ref?.current;
let {draggingKeys} = globalDndState;
let isInternal = isInternalDropOperation(ref);
Copy link
Member Author

@LFDanLu LFDanLu Sep 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bunch of these isInternal checks use ref instead of relying on the global state's dropCollectionRef because I felt it was safer this way (global state is spooky in general). Since these are all within useDroppableCollection, the ref should be equal to dropCollectionRef for the most part (some exceptions exist where we want to calculate isInternal before we even set dropCollectionRef)

@adobe-bot
Copy link

Base automatically changed from dnd_api_simplification to main September 20, 2022 17:18
@LFDanLu LFDanLu force-pushed the dnd_api_simplification_followups branch from d69cdbc to 60993aa Compare September 20, 2022 21:29
@adobe-bot
Copy link

…r Android

slight optimization in DragManager by removing extraneous setDropCollectionRef in favor of drag end handling isInternal logic instead. Also fix detection of Android virtual clicks, element clicked via click() will have pointerType="" and detail=0 so we can rely on the previous detail=0 logic for that case instead
directory may be a type that is common among user data so it may accidentally conflict with our special directory keyword in acceptedDragTypes. To resolve this we change it so acceptedDragTypes allows a Symbol equivalent that we defined for directory
@LFDanLu LFDanLu changed the title (WIP) Update simplified DnD handler api and memoize useDnDHooks Update simplified DnD handler api and memoize useDnDHooks Sep 20, 2022
@@ -26,7 +26,6 @@
"@react-aria/utils": "^3.13.3",
"@react-aria/visually-hidden": "^3.4.1",
"@react-stately/dnd": "3.0.0-alpha.10",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was doing some auditing and have a clarifying question: should things like @react-stately/dnd/@react-types/* be in devDeps instead if they are only used to import types/interfaces? I was under the impression that we could do a import type for things like that and thus avoid needing to include them within the dependencies because they only matter during dev (aka typechecking)

@@ -33,7 +33,7 @@ export function isVirtualClick(event: MouseEvent | PointerEvent): boolean {
// Android TalkBack's detail value varies depending on the event listener providing the event so we have specific logic here instead
// If pointerType is defined, event is from a click listener. For events from mousedown listener, detail === 0 is a sufficient check
// to detect TalkBack virtual clicks.
if (isAndroid() && (event as PointerEvent).pointerType != null) {
if (isAndroid() && (event as PointerEvent).pointerType) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

click events triggered by .click() will have a pointerType = "" and detail === 0 so we can avoid this check and fallback to the detail === 0 check below

@@ -68,45 +68,46 @@ export interface DnDOptions extends Omit<DraggableCollectionProps, 'preview' | '
}

export function useDnDHooks(options: DnDOptions): DnDHooks {
let {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This diff is really just me moving everything into a single useMemo

@LFDanLu LFDanLu marked this pull request as ready for review September 20, 2022 23:32
@@ -159,12 +161,12 @@ export class DragTypes implements IDragTypes {
this.includesUnknownTypes = !hasFiles && dataTransfer.types.includes('Files');
}

has(type: string) {
if (this.includesUnknownTypes || (type === 'directory' && this.types.has(GENERIC_TYPE))) {
has(type: string | DirectorySymbolType) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does string | symbol work here? Might be good to keep this a little more vague rather than only allowing directorySymbol, in case we add more special symbol types in the future.

@@ -18,6 +18,8 @@ import {Key, RefObject} from 'react';
import {useId} from '@react-aria/utils';

const droppableCollectionIds = new WeakMap<DroppableCollectionState, string>();
export const directorySymbol = Symbol();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We haven't really done something like this before, but do we want to use upper case for constants? I think that's a fairly common convention. Something like DIRECTORY_DRAG_TYPE? If not, I still think naming it with drag type in the name rather than "symbol" makes sense.

...(isDraggable ? dragHooks : {}),
...(isDroppable ? dropHooks : {}),
...(isDraggable || isDroppable ? {isVirtualDragging} : {})
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of creating the objects unconditionally and then merging them, you could assign properties from within an if statement? Maybe a little more efficient.

let hooks = {};
if (isDraggable) {
  hooks.useDraggableCollectionState = /* ... */
}

// etc.

also expand acceptedDragTypes to accept any symbol in case we add more unique drag types in the future
also skips calling the util handlers if filteredItems is empty
this allows the user to define what drop operations a droppable collection accepts, making it so copy or link can become the new default operation.
@@ -70,9 +70,9 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
let filteredItems = items;
if (acceptedDragTypes) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this check isn't needed anymore? Or maybe it should be if (acceptedDragTypes !== 'all' || shouldAcceptItemDrop) as an optimization?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yep, thanks for catching this

@adobe-bot
Copy link

this avoids the need for adding a dev dep of react-spectrum/dnd to the types packages
@@ -21,7 +21,6 @@ import {
SpectrumSelectionProps,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would love to delete the @react-types/list package now that aria/spectrum define and export the types but a bit worried about if people are using it since it have been released.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it be weird to change this package to re-export the types from aria/spectrum instead? only for backward compatibility I guess. not sure how important tho

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feels a bit weird to have the dependencies go the other way, but at least it wouldn't be circular since nothing else should depend on this types package. I'll go ahead and update

@adobe-bot
Copy link

devongovett
devongovett previously approved these changes Sep 22, 2022
for backcompat. We define and export these props from aria/spectrum packages now, the react-types/list packages is no longer necessary since it is only used for one component
@adobe-bot
Copy link

@adobe-bot
Copy link

@LFDanLu LFDanLu merged commit cb54cf4 into main Sep 22, 2022
@LFDanLu LFDanLu deleted the dnd_api_simplification_followups branch September 22, 2022 23:17
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

Successfully merging this pull request may close these issues.

None yet

5 participants