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

Code before:
import { ViewSettingsMenu } from './components/ViewSettingsMenu';

import type { Modules } from '@strapi/types';

const { INJECT_COLUMN_IN_TABLE } = HOOKS;

/* -------------------------------------------------------------------------------------------------
 * ListViewPage
 * -----------------------------------------------------------------------------------------------*/
const LayoutsHeaderCustom = styled(Layouts.Header)`
  overflow-wrap: anywhere;
`;

const ListViewPage = () => {
  const { trackUsage } = useTracking();
  const navigate = useNavigate();
  const { formatMessage } = useIntl();
  const { toggleNotification } = useNotification();
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);

  usePersistentPartialQueryParams('STRAPI_LIST_VIEW_SETTINGS:', ['sort', 'filters', 'pageSize']);

  const { collectionType, model, schema } = useDoc();
  const { list } = useDocumentLayout(model);

  const [displayedHeaders, setDisplayedHeaders] = usePersistentState<ListFieldLayout[]>(
    `STRAPI_LIST_VIEW_DISPLAY_HEADERS:${model}`,
    []
  );

  /**
   * 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));

Review comment (suggestion):
Here I would suggest to use useScopedPersistentState instead to scope stored data to a Strapi instance. Only thing is that it's not currently exported from the admin package so we would need to add it first in `packages/core/admin/admin/src/index.ts` line 61

Code after:
import { ViewSettingsMenu } from './components/ViewSettingsMenu';

import type { Modules } from '@strapi/types';

const { INJECT_COLUMN_IN_TABLE } = HOOKS;

/* -------------------------------------------------------------------------------------------------
 * ListViewPage
 * -----------------------------------------------------------------------------------------------*/
const LayoutsHeaderCustom = styled(Layouts.Header)`
  overflow-wrap: anywhere;
`;

const ListViewPage = () => {
  const { trackUsage } = useTracking();
  const navigate = useNavigate();
  const { formatMessage } = useIntl();
  const { toggleNotification } = useNotification();
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);

  usePersistentPartialQueryParams('STRAPI_LIST_VIEW_SETTINGS:', ['sort', 'filters', 'pageSize']);
  usePersistentPartialQueryParams('STRAPI_LOCALE', ['plugins.i18n.locale'], false);

  const { collectionType, model, schema } = useDoc();
  const { list } = useDocumentLayout(model);

  const [displayedHeaderNames, setDisplayedHeaderNames] = useScopedPersistentState<string[] | null>(
    `STRAPI_LIST_VIEW_DISPLAYED_HEADERS:${model}`,
    null
  );

  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));