Reagieren Sie auf unnötiges Rendern des Elements

Sep 30 2020

Ich habe gerade angefangen, React zu lernen und habe eine kleine App zusammengestellt, die eine Anführungszeichen-API aufruft. Die API verfügt über einen Endpunkt, der ein zufälliges Anführungszeichen zurückgibt. Wenn die App zum ersten Mal geladen wird, ruft sie die API auf und zeigt ein Angebot an. Außerdem gibt es eine Schaltfläche, auf die geklickt werden kann, um ein neues zufälliges Angebot zu erhalten (neuer Aufruf der API).

Ich habe eine Root-Komponente namens App. Diese Komponente verfügt als untergeordnetes Element über eine QuoteWrap-Komponente. Die QuoteWrap-Komponente hat zwei untergeordnete Elemente: die Schaltfläche, mit der ein neues zufälliges Zitat abgerufen wird, und eine Quote-Komponente, die den Autor des Zitats und das Zitat selbst anzeigt. Dies ist der Code in der QuoteWrap-Komponente:

export default function QuoteWrap() {
    const { quoteData, isLoading, fireNewCall } = useQuote();

    const handleClick = () => {
        fireNewCall();
    };

    return(
        <>
            <button onClick={handleClick}>Get random quote</button>
            
            { isLoading ? 
                <h2>Loading...</h2>
            :
                <Quote author={quoteData.author} quote={quoteData.quote} />
            }
        </>
    );
}

useQuote () ist ein benutzerdefinierter Hook, der die Aufrufe der API verwaltet und 3 Werte zurückgibt: 1- die Daten, 2- wenn ein Aufruf ausgeführt wird und 3- eine Funktion zum Aufrufen der API.

Offensichtlich wird jedes Mal, wenn auf die Schaltfläche geklickt wird, die gesamte QuoteWrap-Komponente neu gerendert (wenn sich quoteData und isLoading ändern). Aber wirklich, die Schaltfläche muss nicht neu gerendert werden, da sie sich nie ändert.

Also dachte ich: ok, ich kann den Button nach oben zur App-Komponente bewegen. Aber dann habe ich keinen Zugriff auf die fireNewCall-Funktion im useQuote-Hook.

Wie kann ich verhindern, dass die Schaltfläche erneut gerendert wird? Ist es in diesem Fall überhaupt wichtig oder bin ich zu besessen von React-Renderings?

Vielen Dank!

Antworten

Benjamin Sep 30 2020 at 01:18

Ihre Komponente wird jedes Mal neu gerendert, wenn sich die handleClick-Funktion ändert. Dies ist jedes Mal, wenn QuoteWrap gerendert wird.

Die Lösung ist der useCallback-Hook. useCallback gibt bei jedem Rendern von QuoteWrap dieselbe Funktion an handleClick zurück, sofern sich die Abhängigkeiten nicht geändert haben.

https://reactjs.org/docs/hooks-reference.html#usecallback

Sie würden es so verwenden:

  const handleClick = useCallback(() => {
    fireNewCall();
  },[fireNewCall]);

fireNewCall ist die Abhängigkeit. Solange useQuote eine stabile fireNewCall-Funktion zurückgibt, wird Ihre Schaltfläche nicht erneut gerendert, da sich die handleClick-Eigenschaft nicht geändert hat.

VietDinh Sep 30 2020 at 01:15

Ich denke, Sie könnten zu besessen von React-Renderings sein. Die Schaltfläche sollte neu gerendert werden, da handleClicksie in fireNewCalleinigen Fällen geändert werden sollte, wenn sie geändert wird. Auch wenn, handleClickwird nie geändert. Sie müssen nicht über ein Element nachdenken, das neu gerendert wird.

BernardLeech Sep 30 2020 at 01:24

So ziemlich das, was Benjamin und Viet gesagt haben - in Ihrem ursprünglichen Code wird handleClick bei jedem Rendern eine neue Funktion zugewiesen. Sie können React.useCallbackdie ursprüngliche Funktionsreferenz verwenden und sie nur aktualisieren, wenn sich etwas im Abhängigkeitsarray ändert. In diesem Fall muss sie nur fireNewCallin das Abhängigkeitsarray verschoben werden.

Aber wie Viet sagt, sei nicht zu besessen davon. Die Verwendung React.useCallbackkann Ihren Code sogar verlangsamen. Schauen Sie sich Kent C. Dodds an, wann Sie Memo und den Callback- Beitrag verwenden sollten, um weitere Informationen zu erhalten.