DEV Community

Cover image for Filtrare una lista con useMemo in una pagina Nextjs
Paolo Carraro
Paolo Carraro

Posted on

Filtrare una lista con useMemo in una pagina Nextjs

Cosa ho imparato oggi? che un buon modo per filtrare una lista lato client, quindi senza richieste al backend, qualora la lista si presenta di un numero tale di elementi da permetterlo, è usare l'hook in _react _useMemo.
Questo hook mantiene memorizzata un'istanza di un oggetto nei successivi rendering del componente permettendo però un aggiornamento controllato al cambio di uno stato impostato come dipendenza.

Nel caso del filtraggio della lista la dipendenza è l'oggetto che rappresenta i criteri di ricerca/filtro.

Definiamo prima di tutto lo stato della nostra pagina di presentazione lista

type UsersPageProps =
  | {
      status: "successful";
      data: User[];
    }
  | {
      status: "error";
      error: string;
    };
Enter fullscreen mode Exit fullscreen mode

Poi definiamo la funzione per risolvere lato server l'ottenimento dei dati dal backend

export const getServerSideProps: GetServerSideProps<UsersPageProps> = async (context) => {
  try {
    const props: UsersPageProps = {
      status: "successful",
      data: await api.get("/user"),
    };
    return { props };
  } catch (err: any) {
    const props: UsersPageProps = {
      status: "error",
      error: parseResponseError(err),
    };
    return { props };
  }
};
Enter fullscreen mode Exit fullscreen mode

Ora possiamo definire la nostra pagina con la presentazione dei dati (il template è volutamente semplificato per lo scopo del post)

  return (
    <div className="page-main">
        <section>
          {props.status === 'successful' ? (
            <>
              <UsersFilterForm onFiltersChanged={onFiltersChange} />
              <UsersTable data={filteredUsers ?? []} />
            </>
          ) : props.status === 'error' ? (
            <Alert>{props.error}</Alert>
          ) : null
          }
        </section>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Ora vediamo invece come gestire il cambio dei filtri e la conseguente lista presentata dalla collezione filteredUsers

const [userFilters, setUserFilters] = useState<UsersFilters>({ name: "", status: "NONE" });
const onFiltersChange = (filters: UsersFilters) => {
  setUserFilters({ ...filters });
};
const filteredUsers = useMemo(() => {
  if (props.status === "successful") {
    let filteredData = props.data;

    if (userFilters.name) {
      filteredData = props.data.filter((u) => {
        if (
          u.firstname.toLocaleLowerCase().includes(userFilters.name!.toLocaleLowerCase()) ||
          u.lastname.toLocaleLowerCase().includes(userFilters.name!.toLocaleLowerCase())
        ) {
          return true;
        }
      });
    }

    if (userFilters.status && userFilters.status !== "NONE") {
      filteredData = result.filter((u) => u.status === userFilters.status);
    }

    return filteredData;
  }
}, [userFilters]);
Enter fullscreen mode Exit fullscreen mode

Possiamo notare quindi che oltre allo useState che gestisce le mutazioni dei filtri userFilters useremo useMemo con dipendenza proprio lo stato dei filtri per ridurre la nostra lista ai criteri richiesti.

E voi che metodi usate?

Top comments (0)