javascript - איך אני יכול למנוע מרכיב מורכב לעבור רינדור מחדש?
אני משתמש בקונטקסט של React, וכל מה שהוא מכיל כרגע הם 3 פריטים: contacts ו-editingContact, ו-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>
)
}
הנה איך זה משמש:
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 />}
</>
);
};
ל-<Card /> יש כרגע רק כפתור עריכה, שמפעיל את contactsContext.editContact(). עם זאת, כל פעם שהפונקציה הזו מופעלת, כל ה-Cards מתרנדרים מחדש. שמתי console.log('card') בכל Card, והוא מדפיס card 10 פעמים (יש לי 10 אנשי קשר כרגע).
מה אני עושה לא נכון?
תשובה #1
התנהלה דיון בנושא ב-Github של React, בעיקר יש שלוש אפשרויות פתרון לכך:
- אפשרות 1 (מומלצת): לפצל הקשרים שלא משתנים יחד
- אפשרות 2: חלקו את הקומפוננטה שלכם לשניים, שימו
memoביניהם - אפשרות 3: רכיב אחד עם
useMemoבפנים
כדאי לבדוק את הקישור לדוגמאות על זה.