Jak vytvořit komponentu seznamu Select All v React with Next.js

Jak vytvořit komponentu seznamu s výběrem všech pomocí React v aplikaci Next.js.

Začínáme

Pro tento tutoriál použijeme CheatCode Next.js Boilerplate, který nám poskytne výchozí bod pro naši práci. Nejprve naklonujte základní desku:

Terminál

git clone https://github.com/cheatcode/nextjs-boilerplate.git

Dále cd do projektu a nainstalujte jeho závislosti:

Terminál

cd nextjs-boilerplate && npm install

Dále přidejte závislost faker který použijeme ke generování reálných testovacích dat pro náš seznam pro výběr všeho:

Terminál

npm i faker

Nakonec spusťte aplikaci:

Terminál

npm run dev

S aplikací spuštěnou a spuštěnou jsme připraveni začít.

Vytvoření základní komponenty

Abychom mohli začít, nejprve vytvoříme základní komponentu React. Protože je naše uživatelské rozhraní poměrně jednoduché, použijeme vzor funkčních komponent v React:

/pages/users/index.js

import React, { useState } from "react";

const Users = () => {
  const [users] = useState([]);
  const [selectedUsers, setSelectedUsers] = useState([]);

  return (
    <div className="responsive-table">
      <table className="table">
        <thead>
          <tr>
            <th>
              <input
                type="checkbox"
              />
            </th>
            <th className="text-left">Name</th>
            <th className="text-left">Email Address</th>
            <th className="text-center">Last Seen</th>
          </tr>
        </thead>
        <tbody>
          {users.map(({ _id, name, emailAddress, lastSeen }) => {
            return (
              <tr key={_id}>
                <td>
                  <input
                    type="checkbox"
                    value={_id}
                  />
                </td>
                <td className="text-left">{name}</td>
                <td className="text-left">{emailAddress}</td>
                <td className="text-center">{lastSeen}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
};

Users.propTypes = {};

export default Users;

Zde nastavujeme komponentu React, která vykreslí <table></table> uživatelů, přičemž každý uživatel dostane zaškrtávací políčko, pomocí kterého jej můžeme označit jako vybraného v prvním sloupci jeho řádku. V <thead></thead> tabulky přidáme <input type="checkbox" /> který bude sloužit jako zaškrtávací políčko „vybrat vše“ pro celý seznam.

V horní části naší komponenty používáme useState() hook function od React k vytvoření dvou dynamických hodnot:seznam users který vykreslíme do našeho <tbody></tbody> a poté seznam selectedUsers který použijeme k označení zaškrtávacích políček v naší tabulce k označení uživatelů, kteří jsou aktuálně vybráni v uživatelském rozhraní.

Prozatím pro ně nastavujeme výchozí hodnotu na prázdné pole ([] které předáme do useState() ). Dále, abychom skutečně ukázali některé uživatele v našem seznamu, naučíme se, jak generovat některá testovací data za běhu pomocí faker závislost, kterou jsme dříve nainstalovali.

Generování seznamu testovacích uživatelů

Mimo naše Users komponentní funkce, přidejte novou proměnnou testUsers :

/pages/users/index.js

import React, { useState } from "react";
import faker from 'faker';
import { monthDayYearAtTime } from "../../lib/dates";

const testUsers = [...Array(100)].map((item, index) => {
  return {
    _id: `user_${index}`,
    name: faker.name.findName(),
    emailAddress: faker.internet.email(),
    lastSeen: monthDayYearAtTime(faker.date.past()),
  };
});

const Users = () => {
  const [users] = useState(testUsers);
  const [selectedUsers, setSelectedUsers] = useState([]);

  return (
    <div className="responsive-table">
      <table className="table">
        <thead>
          <tr>
            ...
          </tr>
        </thead>
        <tbody>
          {users.map(({ _id, name, emailAddress, lastSeen }) => {
            return (
              <tr key={_id}>
                ...
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
};

Users.propTypes = {};

export default Users;

V horní části našeho souboru jsme importovali dvě věci:faker z faker závislost, kterou jsme nainstalovali dříve, a pomocná funkce zabudovaná do základního kódu, který používáme monthDayYearAtTime což nám pomůže vygenerovat pro každého z našich uživatelů datum „poslední návštěvy“, které bude vhodné pro lidi.

Dále jsme přidali novou proměnnou testUsers které je nastaveno na prázdné pole [] který obsahuje příkaz ...Array(100) . Zde ... je v JavaScriptu známý jako operátor šíření. To má hodnotu, která za ním bezprostředně následuje – zde Array(100) —a šíří to v nadřazeném kontextu, nebo v tomto případě v našem prázdném poli.

Array(100) část zde je úhledný trik využívající JavaScript Array funkce k vytvoření pole 100 prvků. Předáním čísla 100 získáme zpět pole 100 undefined hodnoty. Každých undefined value je rozpoznána jako hodnota v JavaScriptu, což znamená, pokud .map() nad tímto polem, jako bychom byli tady, můžeme zacházet s těmi undefined hodnoty jako zástupné symboly a vrátí skutečné hodnotu v .map() zpětné volání funkce.

Zde uděláme právě to, vrátíme objekt, který nahradí undefined vytvořený Array(100) . Na každý objekt přidáme _id rovno user_ zřetězený s aktuálním indexem pole (nějaké číslo od 0 do 99). Dále pomocí faker knihovny, kterou jsme importovali nahoru, vygenerujeme jméno uživatele s faker.name.findName() získat zpět řetězec celého jména a e-mailovou adresu s faker.internet.email() .

Dále nastavíme lastSeen časové razítko (většinou pro zábavu a aby byl náš příklad konkrétnější), opět pomocí faker získat náhodné datum v minulosti pomocí faker.date.past() . Toto náhodné datum předáme do monthDayYearAtTime() funkci, kterou jsme importovali nahoru, abychom převedli vygenerované datum na lidsky čitelný řetězec.

Nakonec s naším testUsers vygenerovanou hodnotou, nahradíme [] které jsme předali useState() definice pro náš users seznam s naším novým testUsers variabilní. Nyní, když vykreslíme naši komponentu, měli bychom na obrazovce vidět seznam našich testovacích uživatelů.

Výběr jednotlivých uživatelů

Nyní, když máme seznam uživatelů, můžeme implementovat výběr uživatelů. Naším cílem je udělat to tak, abychom mohli udělat jednu ze dvou věcí:

  1. Vyberte a zrušte výběr jednotlivých uživatelů po jednom.
  2. Vyberte nebo zrušte výběr všech uživatelů najednou.

Abychom zvládli první možnost, upravíme <input type="checkbox" /> zahrnout onChange handler a způsob, jak nastavit jeho checked stav:

/pages/users/index.js

import React, { useState } from "react";
import faker from "faker";
import { monthDayYearAtTime } from "../../lib/dates";

const testUsers = [...Array(100)].map((item, index) => { ... });

const Users = () => {
  const [users] = useState(testUsers);
  const [selectedUsers, setSelectedUsers] = useState([]);

  const handleSelectUser = (event) => {};

  return (
    <div className="responsive-table">
      <table className="table">
        <thead>
          ...
        </thead>
        <tbody>
          {users.map(({ _id, name, emailAddress, lastSeen }) => {
            return (
              <tr key={_id}>
                <td>
                  <input
                    type="checkbox"
                    value={_id}
                    checked={selectedUsers.includes(_id)}
                    onChange={handleSelectUser}
                  />
                </td>
                ...
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
};

Users.propTypes = {};

export default Users;

Zde se podíváme na <input type="checkbox" /> vykreslený na začátku každého řádku uživatele, přidali jsme dva atributy:checked a onChange .

Pro checked , nastavíme jej na stejnou hodnotu jako JavaScriptový výraz, který přebírá náš selectedUsers hodnotu stavu a pomocí pole JavaScriptu .includes() metoda, zkontroluje _id uživatele, kterého aktuálně mapujeme v seznamu. Pokud jejich _id se v tomto poli objeví, to znamená, že jde o vybraného uživatele, nebo že jeho zaškrtávací políčko by se mělo zobrazit jako "zaškrtnuté."

Dále pro onChange , předáme funkci, kterou jsme vyškrtli těsně nad naším return příkaz s názvem handleSelectUser . Kdykoli je zaškrtávací políčko zaškrtnuto nebo odškrtnuto, bude tato funkce volána. Pojďme to nyní nastavit tak, aby se skutečně staralo o správu vybraného stavu uživatele.

/pages/users/index.js

import React, { useState } from "react";
import faker from "faker";
import { monthDayYearAtTime } from "../../lib/dates";

const testUsers = [...Array(100)].map((item, index) => { ... });

const Users = () => {
  const [users] = useState(testUsers);
  const [selectedUsers, setSelectedUsers] = useState([]);

  const handleSelectUser = (event) => {
    const userId = event.target.value;

    if (!selectedUsers.includes(userId)) {
      setSelectedUsers([...selectedUsers, userId]);
    } else {
      setSelectedUsers(
        selectedUsers.filter((selectedUserId) => {
          return selectedUserId !== userId;
        })
      );
    }
  };

  return (
    <div className="responsive-table">
      <table className="table">
        <thead>
         ...
        </thead>
        <tbody>
          {users.map(({ _id, name, emailAddress, lastSeen }) => {
            return (
              <tr key={_id}>
                <td>
                  <input
                    type="checkbox"
                    value={_id}
                    checked={selectedUsers.includes(_id)}
                    onChange={handleSelectUser}
                  />
                </td>
                ...
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
};

Users.propTypes = {};

export default Users;

Podívejte se na handleSelectUser Začneme tím, že vezmeme onChange objekt události jako argument, pomocí kterého načte _id uživatele, kterému patří zaškrtávací políčko s event.target.value a uložte jej do proměnné const userId .

Dále naše skutečná práce. Pamatujte, že je třeba zvážit dva scénáře:

  1. Uživatel není mají zaškrtnuté políčko a je třeba je přidat do selectedUsers pole.
  2. Uživatel již má zaškrtnuté políčko a je třeba jej odebrat z selectedUsers pole.

Tady právě to děláme. V prvním případě zkontrolujeme, zda selectedUsers již .includes() userId vytáhli jsme z event.target.value . Pokud ne , používáme setSelectedUsers dostaneme zpět z useState() , předá mu pole, jehož první hodnota je ... rozšíření stávajícího selectedUsers a druhou hodnotu userId chceme přidat. Na druhé straně jsme nastavili pole selectedUsers zpět do stavu, včetně userId zkontrolovali jsme.

Pro druhý scénář — zde v else příkaz — voláme na setSelectedUsers znovu, ale tentokrát použijte JavaScript .filter() metoda filtrování našeho selectedUsers pole, kromě zaškrtnutého userId z pole. Zde selectedUserId !== userId vyhodnotí pouze jako true pokud userId není odpovídat selectedUserId právě probíhá smyčka v .filter() .

Protože to předáváme setSelectedUsers() , získáme filtrovaný selectedUsers nastavit do stavu při spuštění.

Výběr všech uživatelů

Dále, výběr všech uživatelů vyžaduje podobný přístup, ale trochu jednodušší...

/pages/users/index.js

import React, { useState } from "react";
import faker from "faker";
import { monthDayYearAtTime } from "../../lib/dates";

const testUsers = [...Array(100)].map((item, index) => { ... });

const Users = () => {
  const [users] = useState(testUsers);
  const [selectedUsers, setSelectedUsers] = useState([]);

  const handleSelectAllUsers = () => {
    if (selectedUsers.length < users.length) {
      setSelectedUsers(users.map(({ _id }) => _id));
    } else {
      setSelectedUsers([]);
    }
  };

  const handleSelectUser = (event) => { ... };

  return (
    <div className="responsive-table">
      <table className="table">
        <thead>
          <tr>
            <th>
              <input
                type="checkbox"
                checked={selectedUsers.length === users.length}
                onChange={handleSelectAllUsers}
              />
            </th>
            <th className="text-left">Name</th>
            <th className="text-left">Email Address</th>
            <th className="text-center">Last Seen</th>
          </tr>
        </thead>
        <tbody>
          {users.map(({ _id, name, emailAddress, lastSeen }) => {
            return (
              <tr key={_id}>
                ...
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
};

Users.propTypes = {};

export default Users;

Protože naším cílem je vybrat vše našich uživatelů, nejprve na <input type="checkbox" /> v našem <thead></thead> , nastavíme checked atribut rovný selectedUsers.length === users.length . Pokud je to pravda, znamená to, že jsme vybrali všechny dostupné uživatele.

Opět, jak jsme viděli dříve, přidáme onChange atribut nastaven na funkci, tentokrát definující novou s názvem handleSelectAllUsers .

Když se podíváme na tuto funkci, stejně jako jsme se naučili předtím, než musíme zpracovat stav nezaškrtnutý -> zaškrtnutý, stejně jako stav zaškrtnutý -> nezaškrtnutý. Chcete-li to udělat zde, pro první případ, pokud selectedUsers.length je menší než users.length , my setSelectedUsers rovná se novému poli vytvořenému .map() přes naše users pole, odtrhněte _id pole na každém uživateli. Tím se dostane všechny _id našeho uživatele s do selectedUsers , což znamená selectedUsers.includes(userId) vedle každého uživatele bude true a zobrazí uživatele jako zaškrtnutého.

Dále v else Inverzní je zde stejně snadné jako volání na setSelectedUsers() , předáte mu prázdné pole [] což znamená, že aktuálně nejsou vybráni žádní uživatelé.

Zabalení

V tomto tutoriálu jsme se naučili, jak vytvořit komponentu select-all pomocí React.js. Naučili jsme se, jak definovat komponentu React, která vykresluje tabulku dynamicky generovaných uživatelů se zaškrtávacím políčkem pro výběr vedle každého uživatele a zaškrtávacím políčkem „vybrat vše“ v horní části tabulky.

Také jsme se naučili, jak napsat dvě funkce:jednu pro výběr a zrušení výběru jednotlivých uživatelů a jednu pro výběr a zrušení výběru všech uživatelů.