Heim  >  Artikel  >  Web-Frontend  >  Was die neue Reaktion an den Tisch gebracht hat – verschaffen Sie sich ein klares Verständnis

Was die neue Reaktion an den Tisch gebracht hat – verschaffen Sie sich ein klares Verständnis

Linda Hamilton
Linda HamiltonOriginal
2024-11-24 13:16:15357Durchsuche

React 19 erschien am 25. April 2024. Die JavaScript-Welt verändert sich so schnell, dass es manchmal überwältigend sein kann, Schritt zu halten. Aber wenn diese Änderungen Ihr Leben als React-Entwickler einfacher machen sollen, lohnt es sich, einen Blick darauf zu werfen, oder? Da React ein so wichtiger Teil dieses Ökosystems ist, ist es ein Muss, auf dem Laufenden zu bleiben.

Das Beste an React 19 ist, dass es sich darauf konzentriert, die Dinge einfacher zu machen. Die Updates sollen das Erlernen von React erleichtern und Ihnen mehr Zeit für die Erstellung geben, anstatt sich mit kniffligen Setups herumzuschlagen. Einige der neuen Funktionen sind wirklich bahnbrechend und könnten einen großen Unterschied in Ihrer Arbeitsweise machen, Sie sollten sie sich also auf keinen Fall entgehen lassen.

Ich versuche immer, die Dinge leicht verständlich zu erklären, ohne komplizierte Worte einzubauen. Dieser Artikel ist keine Ausnahme. Mein Ziel ist es, sicherzustellen, dass Sie alles klar verstehen. Lassen Sie uns also gemeinsam die tollen Updates in React 19 erkunden!

Denken Sie daran, dass React 19 noch nicht ganz stabil ist. Derzeit heißt es React Canary. Denken Sie also daran, dass es eigentlich nicht für die Produktion empfohlen wird.

React Compiler

Um unsere React-Anwendungen zu optimieren, verwenden wir einige integrierte Methoden wie useMemo, useCallback oder memo. Dadurch wird React angewiesen, den Code nicht erneut zu kompilieren, wenn sich die Eingaben nicht ändern. Wenn Sie jedoch vergessen, Memoisierung anzuwenden, führt dies zur Verschwendung von React-Ressourcen und Rechenleistung. Um dem entgegenzuwirken, hat React 19 den React Compiler eingeführt. Der neue Compiler von React ist das Augapfel der neuen Version der 19. Version. Der neue Compiler optimiert Ihren Code hinter den Kulissen, sodass Sie diese Haken fallen lassen und sich auf das Schreiben schöner, sauberer React-Komponenten konzentrieren können.

Kurz gesagt, Sie müssen Ihre Funktionen nicht mit useMemo oder useCallback umschließen, um die Leistung zu optimieren, und Sie müssen Ihre Komponente auch nicht mit Memo umschließen, um ein erneutes Rendern Ihrer Komponenten zu verhindern.

Aktionen (Transition-Hook verwenden)

Lass uns etwas Kauderwelsch reden?!! Ist Ihnen aufgefallen, dass der useTransition-Hook vor der Veröffentlichung von React 19 kaum erwähnt wurde? Oder liegt es nur an mir? Nun, zumindest ist mir das aufgefallen, insbesondere bei Junior-Entwicklern. Wie auch immer, lassen Sie mich Ihnen eine Vorstellung davon geben, wie es in der vorherigen Version funktioniert hat, und dann werden wir sehen, warum es jetzt eine so wichtige Funktion ist.

useTransition gibt ein Array mit zwei Elementen zurück: der Funktion „startTransition“ und dem booleschen Wert „isPending“. Sie können Ihre Statusaktualisierungen in die startTransition-Funktion einschließen, um sie als Übergänge (Code mit geringerer Priorität) zu markieren. Das bedeutet, dass der mit startTransition umschlossene Teil zu arbeiten beginnt, nachdem die anderen kontinuierlichen Aufgaben abgeschlossen sind.

In React 18 hat die startTransition-Funktion asynchrone Funktionen nicht direkt unterstützt. Dies stellte eine Einschränkung dar, da startTransition darauf ausgelegt war, Updates mit niedriger Priorität zu kennzeichnen, asynchrone Logik jedoch nicht nativ verarbeiten konnte.

In React 19 wurde diese Einschränkung behoben. Jetzt unterstützt startTransition asynchrone Funktionen, was bedeutet, dass Sie darin asynchrone Aufgaben ausführen können (z. B. Datenabruf), während diese Aktualisierungen als Übergänge markiert bleiben. Diese Verbesserung ermöglicht eine flexiblere und intuitivere Nutzung von startTransition, sodass es sich wie eine „neue“ Funktion anfühlt, obwohl es sich technisch gesehen um eine Verbesserung einer vorhandenen Funktion handelt.

?
Per Konvention werden Funktionen, die asynchrone Übergänge verwenden, „Aktionen“ genannt.

Zum Beispiel könnten Sie den Status „Ausstehend“ und „Fehler“ in useState:
behandeln

// Before Actions
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, setIsPending] = useState(false);

  const handleSubmit = async () => {
    setIsPending(true);
    const error = await updateName(name);
    setIsPending(false);
    if (error) {
      setError(error);
      return;
    } 
    redirect("/path");
  };

  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button onClick={handleSubmit} disabled={isPending}>
        Update
      </button>
      {error && <p>{error}</p>}
    </div>
  );
}

React 19 unterstützt die Verwendung asynchroner Funktionen in Übergängen, um ausstehende Status, Fehler, Formulare und optimistische Aktualisierungen automatisch zu verarbeiten. Sie können beispielsweise useTransition verwenden, um den ausstehenden Status für Sie zu verwalten:

// Using pending state from Actions
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, startTransition] = useTransition();

  const handleSubmit = () => {
    startTransition(async () => {
      const error = await updateName(name);
      if (error) {
        setError(error);
        return;
      } 
      redirect("/path");
    })
  };

  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button onClick={handleSubmit} disabled={isPending}>
        Update
      </button>
      {error && <p>{error}</p>}
    </div>
  );
}

Der asynchrone Übergang setzt den Status „isPending“ sofort auf „true“, stellt die asynchrone(n) Anforderung(en) und schaltet „isPending“ nach allen Übergängen auf „false“. Dadurch können Sie die aktuelle Benutzeroberfläche reaktionsfähig und interaktiv halten, während sich die Daten ändern.

Aktionen

Das React-Team hat Unterstützung für die Übergabe von Funktionen als Aktion hinzugefügt.

export default function App() {
    const [name, setName] = useState(
        () => JSON.parse(localStorage.getItem("name")) || "Anonymous user"
    )

    async function formAction(formData){
        try {
            const newName = await updateNameInDB(formData.get("name"))
            setName(newName)
        }
    }

    return (
        <>
            <p className="username">
                Current user: <span>{name}</span>
            </p>
            <form action={formAction}>
                <input
                    type="text"
                    name="name"
                    required
                />
                <button type="submit">Update</button>
            </form>
        </>
    )
}

Die formAction-Funktion (Sie können alles benennen) ruft Ihnen die Formulardaten innerhalb ihres Parameters ab. Jedes Feld wird durch ein Namensattribut gekennzeichnet. Daher müssen Sie bei der Benennung der Eingaben vorsichtig sein. Der formData-Parameter ist eigentlich das native FormData-Web-API-Objekt. Sie können es in den MDN-Webdokumenten herausfinden. Eine weitere gute Sache ist, dass Sie event.preventDefault() nicht anwenden müssen, da es von React verarbeitet wird.

Wenn eine Formularaktion erfolgreich ist, setzt React das Formular automatisch zurück. Wenn Sie jedoch das Manuell können Sie die neue requestFormReset React DOM API aufrufen.

Neuer Hook: useActionState

?
React.useActionState hieß in den Canary-Versionen zuvor ReactDOM.useFormState, wurde jedoch in useFormState.

umbenannt und ist veraltet

useActionState verfolgt den Komponentenstatus und den ausstehenden Status und stellt eine verpackte Aktionsfunktion zur Verwendung im Formular oder an jedem anderen Ort bereit, an dem wir möglicherweise eine Mutation durchführen möchten.

Hier ist ein Beispiel, um es anschaulicher aufzuschlüsseln:

import { useActionState } from "react"
import { updateNameInDB } from "../api/user"

export default function App() {
    const [user, formAction, isPending] = useActionState(insertName, {
        name: "John Doe",
        error: null
    })

    async function insertName(prevState, formData){
        try {
            const response = await updateNameInDB(formData.get("name"))
            return {name: response.name}
        }catch(error){
            return {...prevState, error: error.error}
        }
    }

    return (
        <>
            {user?.name && (
                <p>



<p>How this hook works is described with reference to the example:</p>

<ol>
<li><p>The first argument of the useActionState hook is the "Action" function, which is defined here as insertName.</p></li>
<li><p>The second argument is the initial state, which is accessible through the first element of the result array. In this example, the initial state includes name and error, and the state is represented as user in the component.</p></li>
<li><p>The insertName function returns the updated state. If the operation is successful, it updates the name property. If an error occurs, it updates the error property while preserving the rest of the previous state.</p></li>
<li>
<p>The result of the useActionState hook is an array with three elements:</p>

<ul>
<li>The current state (user): Reflects the latest state of the data.</li>
<li>A dispatchable function (formAction): Triggers the action when called, as seen in the form element's action attribute.</li>
<li>A pending state (isPending): Tracks whether the action is currently in progress, useful for managing transitions or loading indicators.</li>
</ul>
</li>
</ol>

<h2>
  
  
  New Hook: useOptimistic
</h2>

<p>When it’s performing a data mutation and to show the final state right after the user instructs (could be a tap on a button) or you could say optimistically while the async request is underway, you need to use this hook. Here is a demonstration how you can do this:<br>
</p>

<pre class="brush:php;toolbar:false">function ChangeName({currentName, onUpdateName}) {
  const [optimisticName, setOptimisticName] = useOptimistic(currentName);

  const submitAction = async (formData) => {
    const newName = formData.get("name");
    setOptimisticName(newName);
    const updatedName = await updateName(newName);
    onUpdateName(updatedName);
  };

  return (
    <form action={submitAction}>
      <p>Your name is: {optimisticName}</p>
      <p>
        <label>Change Name:</label>
        <input
          type="text"
          name="name"
          disabled={currentName !== optimisticName}
        />
      </p>
    </form>
  );
}

Der useOptimistic-Hook rendert den optimisticName sofort, während die updateName-Anfrage ausgeführt wird. Wenn die Aktualisierung abgeschlossen ist, fügt React den aktualisierten Wert in currentName ein. Wenn bei der Aktualisierung Fehler auftreten, wechselt React automatisch zurück zum Wert currentName.

Neuer Hook: useFormStatus

Mit dem Hook „useFormStatus“ behalten Sie den Überblick über Ihre Formulareinsendungen. Warten Sie eine Minute ?! Ist es ein weiterer Haken, um den asynchronen Übergang zu verfolgen? Nun, die Antwort ist sowohl „Ja“ als auch „Nein“. Da Sie den useActionState-Hook bereits kennengelernt haben, könnte man sagen, dass dies ein weiterer Hook zum Verfolgen des asynchronen Übergangs ist. Der useFormStatus löst jedoch keine Aktion aus, sondern liefert Statusinformationen über die letzte Formularübermittlung.

// Before Actions
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, setIsPending] = useState(false);

  const handleSubmit = async () => {
    setIsPending(true);
    const error = await updateName(name);
    setIsPending(false);
    if (error) {
      setError(error);
      return;
    } 
    redirect("/path");
  };

  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button onClick={handleSubmit} disabled={isPending}>
        Update
      </button>
      {error && <p>{error}</p>}
    </div>
  );
}

Nun, ich würde sagen, das Wichtigste, was hier zu beachten ist, ist, dass der Hook „useFormStatus“ tatsächlich von „react-dom“ und nicht von „react“ stammt.

useFormStatus liest den Status des übergeordneten

als ob das Formular ein Kontextanbieter wäre. Um Statusinformationen zu erhalten, muss die Submit-Komponente in einem gerendert werden. Der Hook gibt Informationen wie die ausstehende Eigenschaft zurück, die Ihnen sagt, ob das Formular aktiv gesendet wird.

Im obigen Beispiel verwendet Submit diese Informationen, um die drückt, während das Formular gesendet wird.

Neue API: verwenden

Sie können ein Versprechen mit „use“ lesen und React wird die Komponente anhalten, bis das Versprechen aufgelöst wird:

// Using pending state from Actions
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, startTransition] = useTransition();

  const handleSubmit = () => {
    startTransition(async () => {
      const error = await updateName(name);
      if (error) {
        setError(error);
        return;
      } 
      redirect("/path");
    })
  };

  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button onClick={handleSubmit} disabled={isPending}>
        Update
      </button>
      {error && <p>{error}</p>}
    </div>
  );
}

Das obige Beispiel zeigt den Anwendungsfall der Use-API. „Comments“ ist eine Komponente, die ein Versprechen namens „commentsPromise“ verbraucht. Das Versprechen wird von der neuen Nutzungs-API verbraucht, wodurch die Komponente angehalten wird. Übrigens müssen Sie die Komponente mit Suspense-Fallback umschließen.

Die Verwendung der API unterliegt einer Einschränkung, die Sie beachten müssen. Die Einschränkung besteht darin, dass jedes Mal, wenn die Verwendungs-API, die die Komponente enthält, erneut gerendert wird, ein weiteres Versprechen erstellt wird, das zu einer schlechten Leistung führt. Im Grunde gibt es also keinen Caching-Mechanismus. Hier ist ihre vorsichtige Anmerkung aus dem Release-Blog:

What New React Has Brought to The Table - Get Clear Understanding

Die Verwendung der API liest auch Daten aus dem Kontext. Um beispielsweise Kontextwerte zu lesen, übergeben wir den Kontext einfach an use() und die Funktion durchläuft den Komponentenbaum, um den nächstgelegenen Kontextanbieter zu finden.

Im Gegensatz zum useContext()-Hook zum Lesen von Kontext kann die use()-Funktion innerhalb von Bedingungen und Schleifen in unseren Komponenten verwendet werden!

export default function App() {
    const [name, setName] = useState(
        () => JSON.parse(localStorage.getItem("name")) || "Anonymous user"
    )

    async function formAction(formData){
        try {
            const newName = await updateNameInDB(formData.get("name"))
            setName(newName)
        }
    }

    return (
        <>
            <p className="username">
                Current user: <span>{name}</span>
            </p>
            <form action={formAction}>
                <input
                    type="text"
                    name="name"
                    required
                />
                <button type="submit">Update</button>
            </form>
        </>
    )
}

ref als Requisite (keine ForwardRef)

In React 19 können Sie Refs wie jede andere Requisite übergeben, was zur Abwertung von forwardRef führt. Dies optimiert Ihren Komponentencode und macht die Ref-Verarbeitung zum Kinderspiel. ?

import { useActionState } from "react"
import { updateNameInDB } from "../api/user"

export default function App() {
    const [user, formAction, isPending] = useActionState(insertName, {
        name: "John Doe",
        error: null
    })

    async function insertName(prevState, formData){
        try {
            const response = await updateNameInDB(formData.get("name"))
            return {name: response.name}
        }catch(error){
            return {...prevState, error: error.error}
        }
    }

    return (
        <>
            {user?.name && (
                <p>



<p>How this hook works is described with reference to the example:</p>

<ol>
<li><p>The first argument of the useActionState hook is the "Action" function, which is defined here as insertName.</p></li>
<li><p>The second argument is the initial state, which is accessible through the first element of the result array. In this example, the initial state includes name and error, and the state is represented as user in the component.</p></li>
<li><p>The insertName function returns the updated state. If the operation is successful, it updates the name property. If an error occurs, it updates the error property while preserving the rest of the previous state.</p></li>
<li>
<p>The result of the useActionState hook is an array with three elements:</p>

<ul>
<li>The current state (user): Reflects the latest state of the data.</li>
<li>A dispatchable function (formAction): Triggers the action when called, as seen in the form element's action attribute.</li>
<li>A pending state (isPending): Tracks whether the action is currently in progress, useful for managing transitions or loading indicators.</li>
</ul>
</li>
</ol>

<h2>
  
  
  New Hook: useOptimistic
</h2>

<p>When it’s performing a data mutation and to show the final state right after the user instructs (could be a tap on a button) or you could say optimistically while the async request is underway, you need to use this hook. Here is a demonstration how you can do this:<br>
</p>

<pre class="brush:php;toolbar:false">function ChangeName({currentName, onUpdateName}) {
  const [optimisticName, setOptimisticName] = useOptimistic(currentName);

  const submitAction = async (formData) => {
    const newName = formData.get("name");
    setOptimisticName(newName);
    const updatedName = await updateName(newName);
    onUpdateName(updatedName);
  };

  return (
    <form action={submitAction}>
      <p>Your name is: {optimisticName}</p>
      <p>
        <label>Change Name:</label>
        <input
          type="text"
          name="name"
          disabled={currentName !== optimisticName}
        />
      </p>
    </form>
  );
}

Das React-Team hat beschlossen, „forwardRef“ in den kommenden Versionen als veraltet zu deklarieren.

React-Server-Komponenten

Wissen Sie übrigens, dass React Server Components (RSCs) eine React-Funktion sind, die serverseitiges Rendering unterstützt, aber Frameworks wie Next.js haben RSCs angenommen und sie nahtlos in ihren Workflow integriert. Wenn Sie neu im Ökosystem sind, klären Sie dies vorher und beginnen Sie mit der Untersuchung seines Mechanismus.

React Server Components sind eine neue Funktion, die in React 19 eingeführt wird und es uns ermöglicht, zustandslose React-Komponenten zu erstellen, die auf dem Server ausgeführt werden.

Da React Server-Komponenten auf einem Webserver ausgeführt werden können, können sie für den Zugriff auf die Datenschicht verwendet werden, ohne mit einer API interagieren zu müssen!

// Before Actions
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, setIsPending] = useState(false);

  const handleSubmit = async () => {
    setIsPending(true);
    const error = await updateName(name);
    setIsPending(false);
    if (error) {
      setError(error);
      return;
    } 
    redirect("/path");
  };

  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button onClick={handleSubmit} disabled={isPending}>
        Update
      </button>
      {error && <p>{error}</p>}
    </div>
  );
}

Damit müssen wir keinen API-Endpunkt verfügbar machen oder zusätzliche clientseitige Abruflogik verwenden, um Daten direkt in unsere Komponenten zu laden. Die gesamte Datenverarbeitung erfolgt auf dem Server.

Beachten Sie, dass Serverkomponenten auf dem Server und nicht im Browser ausgeführt werden. Daher können sie keine herkömmlichen React-Komponenten-APIs wie useState verwenden. Um Interaktivität in eine React-Server-Komponenteneinstellung einzuführen, müssen wir Client-Komponenten nutzen, die die Server-Komponenten für die Handhabung der Interaktivität ergänzen.

Bei der Arbeit mit React Server-Komponenten bedeutet „Client verwenden“, dass die Komponente eine Client-Komponente ist, was bedeutet, dass sie den Status verwalten, Benutzerinteraktionen verarbeiten und browserspezifische APIs verwenden kann. Diese Anweisung weist das React-Framework und den Bundler ausdrücklich an, diese Komponente anders zu behandeln als Serverkomponenten, die zustandslos sind und auf dem Server ausgeführt werden.

// Using pending state from Actions
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, startTransition] = useTransition();

  const handleSubmit = () => {
    startTransition(async () => {
      const error = await updateName(name);
      if (error) {
        setError(error);
        return;
      } 
      redirect("/path");
    })
  };

  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button onClick={handleSubmit} disabled={isPending}>
        Update
      </button>
      {error && <p>{error}</p>}
    </div>
  );
}

Auf der anderen Seite sind React-Serverkomponenten die Standardeinstellung, sodass wir oben in den Serverkomponentendateien nicht „Server verwenden“ angeben. Stattdessen sollte „Server verwenden“ nur verwendet werden, um serverseitige Funktionen zu kennzeichnen, die von Client-Komponenten aufgerufen werden können.

export default function App() {
    const [name, setName] = useState(
        () => JSON.parse(localStorage.getItem("name")) || "Anonymous user"
    )

    async function formAction(formData){
        try {
            const newName = await updateNameInDB(formData.get("name"))
            setName(newName)
        }
    }

    return (
        <>
            <p className="username">
                Current user: <span>{name}</span>
            </p>
            <form action={formAction}>
                <input
                    type="text"
                    name="name"
                    required
                />
                <button type="submit">Update</button>
            </form>
        </>
    )
}

Ich denke, dieses Beispiel verdeutlicht es gut.

Abschluss

React 19 heißt immer noch React Canary. Daher ist es keine gute Idee, es für die Produktion zu verwenden. Aber freuen Sie sich mit React 19 auf die Zukunft und machen Sie Ihre Entwicklungserfahrung reibungsloser und angenehmer.

Das obige ist der detaillierte Inhalt vonWas die neue Reaktion an den Tisch gebracht hat – verschaffen Sie sich ein klares Verständnis. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn