javascript - Ako môžem zabrániť tomu, aby sa zložená komponenta znovu renderovala?


Používam react context a momentálne obsahuje iba 3 položky: contacts, editingContact a editContact:

interface ContactsContextProps {
  contacts: Contact[];
  editingContact: Contact;
  editContact: (contact: Contact) => () => void // being lazy and this is from an onClick
}

const ContactsContext = React.createContext<Partial<ContactsContextProps>>({
  editContact: (contact: Contact) => () => {}
})

const ContactsProvider: React.FunctionComponent = props => {
  const [contacts, setContacts] = useState<Contact[]>();
  const [editingContact, setEditingContact] = useState<Contact>();

  React.useEffect(() => {
   // fetch contacts, and setContacts(contacts)
  }, [])

  const editContact = React.useCallback((contact: Contact) => {
    return function() {
      setEditingContact(contact);
    }
  })

  return (
    <ContactsContext.Provider
      value={{
        editingContact,
        editContact,
        contacts
      }}
    >
      {props.children}
    </ContactsContext.Provider>
  )
}

Tu je to, ako sa to používa:

const ContactsList: React.FunctionComponent<{
  contacts: Contact[];
}> = React.memo(props => {
  return (
    <>
      {props.contacts.map(contact => (
        <Card key={contact.id} contact={contact} />
      ))}
    </>
  );
});

const Wrapper: React.FunctionComponent = () => {
  const contactsCtx = React.useContext(ContactsContext);

  return (
    <>
      <Box className={styles.main}>
        <Header />
        {contactsCtx.contacts && <ContactsList contacts={contactsCtx.contacts} />}
      </Box>
      {contactsCtx.editingContact && <EditContactModal />}
    </>
  );
};

Komponent <Card /> momentálne má iba tlačidlo na úpravu, ktoré volá contactsContext.editContact(). Avšak, zakaždým, keď sa toto volá, všetky Karty sa znovu vykreslia. Do každej Karty som vložil console.log('card') a zaznamenáva sa card 10-krát (momentálne mám 10 kontaktov).

Čo robím zle?

Odpoveď č. 1

V diskusii na GitHub issue o Reacte sa objavila debata, v podstate existujú 3 možné riešenia tohto problému:

  • Možnosť 1 (uprednostňovaná): Rozdeľte kontexty, ktoré sa nemenia spolu
  • Možnosť 2: Rozdeľte svoju komponentu na dve časti, medzi ne vložte memo
  • Možnosť 3: Jeden komponent s useMemo vo vnútri

Mali by ste si skontrolovať odkaz pre príklady o tom.