payloadcms / payload

Payload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.
https://payloadcms.com
MIT License
25.74k stars 1.64k forks source link

useListDrawer keeps stale array of collection slugs #5067

Open timotgl opened 9 months ago

timotgl commented 9 months ago

Link to reproduction

No response

Describe the Bug

When using the useListDrawer hook, only the initial value of the collectionSlugs property seems to be used. The hook returns a memoized ListDrawer component, but changing collectionSlugs are not reflected.

My use case is that I don't know the collection slugs to choose from yet, but the component that renders the ListDrawer stays mounted. Once the hook is called again with different collection slugs, it still renders the react select options from the first call. This is due to the usage of collectionSlugsFromProps as initial state in the referenced line I'm assuming.

As a result, the drawer always offers all collections to choose from if the first call to useListDrawer did not include an array with slugs for collectionSlugs, because of this effect kicking in.

To Reproduce

import { useListDrawer } from "payload/components/elements";

const ReproComponent = () => {
  const [selectedCollectionSlug, setSelectedCollectionSlug] = useState<string>("");

  // setSelectedCollectionSlug is called by a lexical command listener!

  // Limit the collections to choose from to ONE (1)
  const [ListDrawer, ListDrawerToggler, { closeDrawer, openDrawer }] = useListDrawer({
    collectionSlugs: selectedCollectionSlug
      ? [selectedCollectionSlug]
      : undefined,
    selectedCollection: selectedCollectionSlug || undefined,
  });

  // This ListDrawer will show ALL collections because of
  // https://github.com/payloadcms/payload/blob/ae7d6f97d205491390f15850e5104c7abded1550/packages/payload/src/admin/components/elements/ListDrawer/index.tsx#L82
  return <ListDrawer onSelect={applySelectedDocument} />;

  // applySelectedDocument is defined somewhere else.
};

Payload Version

2.10.0

Adapters and Plugins

No response

DanRibbens commented 7 months ago

This needs to be fixed for both 2.x and 3.0.