Repository: strapi/strapi
File: packages/core/content-manager/admin/src/pages/ListView/ListViewPage.tsx (TypeScript)

Code before:
   * If the persistent displayedHeaders are not yet initialized, set them to list.layout
   */
  React.useEffect(() => {
    // wait for list.layout to be loaded
    if (list.layout.length === 0) {
      return;
    }

    if (displayedHeaders.length === 0) {
      setDisplayedHeaders(list.layout);
    }
  }, [list.layout]);

  React.useEffect(() => {
    if (!schema?.attributes) return;
    if (displayedHeaders.length === 0) return;
    if (schema.uid !== model) return;

    const allowedDisplayHeaders = displayedHeaders.filter((header) =>
      Object.keys(schema?.attributes).includes(header.name)
    );

    if (allowedDisplayHeaders.length !== displayedHeaders.length) {
      setDisplayedHeaders(allowedDisplayHeaders);
    }
  }, [displayedHeaders]);

  const handleSetHeaders = (headers: string[]) => {
    setDisplayedHeaders(
      convertListLayoutToFieldLayouts(headers, schema!.attributes, list.metadatas)
    );
  };

  const [{ query }] = useQueryParams<{
    plugins?: Record<string, unknown>;
    page?: string;
    pageSize?: string;
    sort?: string;
  }>({
    page: '1',
    pageSize: list.settings.pageSize.toString(),
    sort: list.settings.defaultSortBy
      ? `${list.settings.defaultSortBy}:${list.settings.defaultSortOrder}`
      : '',
  });

  const params = React.useMemo(() => buildValidParams(query), [query]);

  const { data, error, isFetching } = useGetAllDocumentsQuery({
    model,
    params,

Review comment (bug):
Probably related to the dependency arrays of both useEffect, there is a bug when you switch between two list views where one list view has empty display fields.

Step to reproduce:
- Create 2 collection types
- Open the content manager list view of the first collection
- Add many persist a custom list view settings for the list (add as many as you can)
- Open the second collection list view and empty the list view settings
- Now navigate between the two collection and you should see the first one reset the preferences at some point. 

Here is a screen recording about it: https://www.loom.com/share/b4656b0f596f4564aebf01c4dd49fae1

Code after:
  const mapDisplayedHeaders = (headers: ListFieldLayout[]) => headers.map((header) => header.name);

  const displayedHeaders: ListFieldLayout[] = React.useMemo(() => {
    if (
      !displayedHeaderNames ||
      !list.metadatas ||
      Object.keys(list.metadatas).length <= 0 ||
      !schema?.attributes
    )
      return [];

    return convertListLayoutToFieldLayouts(displayedHeaderNames, schema.attributes, list.metadatas);
  }, [displayedHeaderNames, schema, list]);

  const handleSetHeaders = (headers: string[]) => {
    setDisplayedHeaderNames(headers);
  };

  const handleResetHeaders = () => {
    setDisplayedHeaderNames(mapDisplayedHeaders(list.layout));
  };

  /**
   * If the persistent displayedHeaders are not yet initialized, set them to list.layout
   */
  React.useEffect(() => {
    // wait for list.layout to be loaded
    if (list.layout.length === 0) {
      return;
    }

    if (!displayedHeaderNames) {
      handleResetHeaders();
    }
  }, [list.layout]);

  React.useEffect(() => {
    if (!schema?.attributes) return;
    if (!displayedHeaderNames || displayedHeaderNames.length === 0) return;
    if (schema.uid !== model) return;

    const allowedDisplayHeaders = displayedHeaderNames.filter((header) =>
      Object.keys(schema?.attributes).includes(header)
    );

    if (allowedDisplayHeaders.length !== displayedHeaderNames.length) {
      handleSetHeaders(allowedDisplayHeaders);
    }
  }, [displayedHeaderNames]);

  const [{ query }] = useQueryParams<{