One place for hosting & domains

      Grundlegendes zu Vue.js Lifecycle Hooks


      Einführung

      Lifecycle Hooks bieten einen Einblick in die Funktionsweise der von Ihnen verwendeten Bibliothek hinter den Kulissen. Mithilfe von Lifecycle Hooks können Sie feststellen, wann Ihre Komponente erstellt, dem DOM hinzugefügt, aktualisiert oder zerstört wird.

      Dieses Diagramm aus der offiziellen Vue.js-Dokumentation erfasst den Vue.js Instance-Lifecycle:

      Vue.js Instance-Lifecycle-Diagramm ansehen

      Dieser Artikel führt Sie in die Erstellung, Montage, Aktualisierung und Zerstörung von Hooks ein.

      Grundlegendes zu Creation Hooks (Initialisierung)

      Creation Hooks sind die allerersten Hooks, die in Ihrer Komponente ausgeführt werden. Mit ihnen können Sie Aktionen ausführen, bevor Ihre Komponente überhaupt zum DOM hinzugefügt wurde. Im Gegensatz zu allen anderen Hooks werden Creation Hooks auch beim serverseitigen Rendern ausgeführt.

      Verwenden Sie Creation Hooks, wenn Sie Dinge in Ihrer Komponente einrichten müssen, sowohl beim Client-Rendering als auch beim Server-Rendering.

      Sie haben keinen Zugriff auf DOM oder das Zielmontageelement (this.$el) innerhalb der Creation Hooks.

      beforeCreate

      Der beforeCreate Hook wird bei der Initialisierung Ihrer Komponente ausgeführt. Daten wurden nicht reaktiv gemacht und Ereignisse wurden noch nicht eingerichtet:

      ExampleComponent.vue

      <script>
      export default {
        beforeCreate() {
          console.log('At this point, events and lifecycle have been initialized.')
        }
      }
      </script>
      

      In diesem Beispiel protokolliert dieser Snippet die Nachricht, wenn der beforeCreate-Hook ausgeführt wird: Zu diesem Zeitpunkt werden Ereignisse und Lebenszyklus initialisiert.

      erstellt

      Sie können auf reaktive Daten und Ereignisse zugreifen, die mit dem erstellten Hook aktiv sind. Vorlagen und Virtual DOM wurden noch nicht montiert oder zurückgegeben:

      ExampleComponent.vue

      <template>
        <div ref="example-element">{{ propertyComputed }}</div>
      </template>
      
      <script>
      export default {
        data() {
          return {
            property: 'Example property.'
          }
        },
      
        computed: {
          propertyComputed() {
            return this.property
          }
        },
      
        created() {
          console.log('At this point, this.property is now reactive and propertyComputed will update.')
          this.property = 'Example property updated.'
        }
      }
      </script>
      

      In diesem Beispiel speichert der Snippet Eigenschaft als Beispieleigenschaft. Wenn der erstellte Hook ausgeführt wird, wird eine Nachricht von An diesem Punkt ist diese.Eigenschaft nun reaktiv und propertyComputed wird aktualisiert, protokolliert. Und dann wird die Eigenschaft in Beispieleigenschaft aktualisiert geändert.

      Später im Lebenszyklus wird {{ propertyComputed }} als Beispieleigenschaft aktualisiert anstelle von Beispieleigenschaft angezeigt.

      In diesem Schritt haben Sie einige Beispiele für Creation Hooks überprüft und sind bereit, zum nächsten Teil des Lebenszyklus zu wechseln, die Mounting Hooks.

      Grundlegendes zu Mounting Hooks (DOM-Eingabe)

      Mounting Hooks sind die am häufigsten verwendeten Hooks. Sie ermöglichen es Ihnen, sofort vor und nach dem ersten Rendern auf Ihre Komponente zuzugreifen. Sie werden jedoch nicht während des serverseitigen Renderings ausgeführt.

      Verwenden Sie Mounting Hooks, wenn Sie auf das DOM Ihrer Komponente sofort vor oder nach dem ersten Rendern zugreifen oder es ändern müssen.

      Verwenden Sie keine Mounting Hooks, wenn Sie Daten für Ihre Komponente bei der Initialisierung abrufen müssen.

      Hinweis: Verwenden Sie stattdessen erstellt (oder erstellt und aktiviert für Komponenten, die am Leben gehalten werden sollen). Besonders, wenn Sie diese Daten während des serverseitigen Renderings benötigen.

      beforeMount

      Der beforeMount Hook wird direkt vor dem ersten Rendering ausgeführt und nachdem die Vorlage oder Renderfunktionen kompiliert wurden:

      ExampleComponent.vue

      <script>
      export default {
        beforeMount() {
          console.log(`At this point, vm.$el has not been created yet.`)
        }
      }
      </script>
      

      In diesem Beispiel protokolliert dieser Snippet bei der Ausführung des beforeMount Hook die Nachricht: Zu diesem Zeitpunkt wurde vm.$el noch nicht erstellt.

      montiert

      Im montierten Hook haben Sie vollen Zugriff auf die reaktive Komponente, die Vorlagen und das zurückgegebene DOM (über this.$el).

      Verwenden Sie zur Änderung des DOM montiert – insbesondere bei der Integration von nicht-Vue-Bibliotheken:

      ExampleComponent.vue

      <template>
        <div ref="example-element">Example component.</div>
      </template>
      
      <script>
      export default {
        mounted() {
          console.log(`At this point, vm.$el has been created and el has been replaced.`);
          console.log(this.$el.textContent) // Example component.
        }
      }
      </script>
      

      In diesem Beispiel protokolliert dieser Snippet die Nachricht, wenn der montierte Hook ausgeführt wird Zu diesem Zeitpunkt wurde vm.$el erstellt und el ersetzt. Außerdem wird eine Nachricht von Beispielinhalt. (this.$el.textContent) protokolliert.

      In diesem Abschnitt haben Sie Anwendungsfälle für Mounting Hooks erkundet. Im nächsten Schritt überprüfen Sie einige Beispiele, die Updating Hooks verwenden.

      Grundlegendes zu Updating Hooks (Diff & Re-render)

      Updating Hooks werden aufgerufen, wenn eine reaktive Eigenschaft, die von Ihrer Komponente verwendet wird, sich ändert oder etwas anderes ein erneutes Rendering verursacht. Sie ermöglichen es Ihnen, den Zyklus watch-compute-render für Ihre Komponente zu haken.

      Verwenden Sie Updating Hooks, wenn Sie wissen müssen, wann Ihre Komponente neu gerendert wird, z. B. für das Debuggen oder das Profiling.

      Verwenden Sie die Updating Hooks nicht, wenn Sie wissen müssen, wann sich eine reaktive Eigenschaft auf Ihrer Komponente ändert. Verwenden Sie stattdessen computed Eigenschaften oder Watchers.

      beforeUpdate

      Der beforeUpdate Hook wird nach Datenänderungen Ihrer Komponente ausgeführt und der Update-Zyklus beginnt, unmittelbar bevor das DOM gepatcht und neu gerendert wird.

      Verwenden Sie beforeUpdate, wenn Sie den neuen Status aller reaktiven Daten auf Ihrer Komponente erhalten müssen, bevor sie tatsächlich zurückgegeben wird:

      ExampleComponent.vue

      <template>
        <div ref="example-element">{{counter}}</div>
      </template>
      
      <script>
      export default {
        data() {
          return {
            counter: 0
          }
        },
      
        created() {
          setInterval(() => {
            this.counter++
          }, 1000)
        },
      
        beforeUpdate() {
          console.log(`At this point, Virtual DOM has not re-rendered or patched yet.`)
          // Logs the counter value every second, before the DOM updates.
          console.log(this.counter)
        }
      }
      </script>
      

      Zuerst speichert dieser Snippet Zähler als 0. Wenn der erstellte Hook ausgeführt wird, wird er den Zähler alle 1000 ms erhöhen. Wenn der beforeUpdate-Hook ausgeführt wird, protokolliert dieses Snippet die Nachricht: Zu diesem Zeitpunkt hat Virtual DOM noch nicht neu gerendert oder gepatcht. Eine Zahl für Zähler wird protokolliert.

      aktualisiert

      Der aktualisierte Hook wird nach Datenänderungen Ihrer Komponente und den Neu-Renderings des DOM ausgeführt.

      Verwenden Sie aktualisiert, wenn Sie nach einer Eigenschaftsänderung auf DOM zugreifen müssen:

      ExampleComponent.vue

      <template>
        <div ref="example-element">{{counter}}</div>
      </template>
      
      <script>
      export default {
        data() {
          return {
            counter: 0
          }
        },
      
        created() {
          setInterval(() => {
            this.counter++
          }, 1000)
        },
      
        updated() {
          console.log(`At this point, Virtual DOM has re-rendered and patched.`)
          // Fired every second, should always be true
          console.log(+this.$refs['example-element'].textContent === this.counter)
        }
      }
      </script>
      

      Zuerst speichert dieser Snippet Zähler als 0. Wenn der erstellte Hook ausgeführt wird, wird er den Zähler alle 1000 ms erhöhen. Wenn der aktualisierte Hook ausgeführt wird, protokolliert dieses Snippet die Nachricht: Zu diesem Zeitpunkt hat Virtual DOM erneut gerendert und gepatcht. und ein boolescher Wert von wahr wird protokolliert, da der gerenderte Wert und der aktuelle Wert gleich sind.

      Nachdem Sie nun die Verwendung der Updating Hooks kennengelernt haben, sind Sie bereit, mehr über Destruction Hooks zu erfahren.

      Grundlegendes zu Destruction Hooks (Teardown)

      Destruction Hooks ermöglichen Ihnen, Aktionen durchzuführen, wenn Ihre Komponente zerstört wird, wie das Übergeben von Analysen und Bereinigungen. Sie werden abgegeben, wenn Ihre Komponente zerstört und aus DOM entfernt wird.

      beforeDestroy

      beforeDestroy wird direkt vor dem Löschen abgegeben. Ihre Komponente wird immer noch vollständig vorhanden und funktionell sein.

      Verwenden Sie beforeDestroy, wenn Sie Ereignisse oder reaktive Abonnements löschen müssen:

      ExampleComponent.vue

      <script>
      export default {
        data() {
          return {
            exampleLeakyProperty: 'This represents a property that will leak memory if not cleaned up.'
          }
        },
      
        beforeDestroy() {
          console.log(`At this point, watchers, child components, and event listeners have not been teared down yet.`)
          // Perform the teardown procedure for exampleLeakyProperty.
          // (In this case, effectively nothing)
          this.exampleLeakyProperty = null
          delete this.exampleLeakyProperty
        }
      }
      </script>
      

      Dieses Snippet speichert zunächst exampleLeakyProperty. Wenn der beforeDestroy Hook ausgeführt wird, protokolliert dieser Snippet die Nachricht An diesem Punkt wurden Watchers, untergeordnete Komponenten und Ereignis-Listener noch nicht zerstört. und dann exampleLeakyProperty gelöscht.

      zerstört

      Bis zu den zerstörten Hook erreichen, ist praktisch nichts mehr in Ihrer Komponente. Alles, was daran hing, wurde zerstört.

      Verwenden Sie zerstört, wenn Sie eine Last-Minute-Bereinigung ausführen oder einen Remote-Server darüber informieren müssen, dass die Komponente zerstört wurde:

      ExampleComponent.vue

      <script>
      import ExampleAnalyticsService from './example-analytics-service'
      
      export default {
        destroyed() {
          console.log(`At this point, watchers, child components, and event listeners have been torn down.`)
          console.log(this)
          ExampleAnalyticsService.informService('Component destroyed.')
        }
      }
      </script>
      

      Zuerst importiert dieser Snippet ExampleAnalyticsService. Wenn der beforeDestroy Hook ausgeführt wird, protokolliert dieser Snippet die Nachricht An diesem Punkt wurden Watchers, untergeordnete Komponenten und Ereignis-Listener zerstört. Was von der Komponente übrig bleibt, wird in die Konsole protokolliert und ExampleAnalyticsService wird an die Nachricht Komponente zerstört übergeben.

      Damit haben Sie Ihre allgemeine Überprüfung der Vue.js Lifecycle Hooks abgeschlossen.

      Andere Hooks

      Es gibt zwei weitere Hooks, aktiviert und deaktiviert. Diese sind für keep-alive Komponenten, ein Thema, das außerhalb des Geltungsbereichs dieses Artikels liegt.

      Es genügt zu sagen, dass sie es Ihnen ermöglichen, zu erkennen, wenn eine Komponente, die in einem Tag <keep-alive></keep-alive> eingegeben wird, ein- oder ausgeschaltet wird. Vielleicht verwenden Sie sie, um Daten für Ihre Komponente abzurufen oder Statusänderungen zu verarbeiten, wobei sie sich als erstellt und beforeDestroy effektiv verhalten, ohne dass eine vollständige Neuerstellung der Komponente erforderlich ist.

      Zusammenfassung

      In diesem Artikel wurden Ihnen verschiedene Lifecycle Hooks vorgestellt, die im Vue.js Instance Lifecycle verfügbar sind. Sie haben die verschiedenen Anwendungsfälle für die Erstellung von Hooks, die Montage von Hooks, die Aktualisierung von Hooks und die Zerstörung von Hooks erkundet.

      Wenn Sie mehr über Vue.js erfahren möchten, lesen Sie unsere Themenseite zu Vue.js für Übungen und Programmierprojekte.



      Source link

      Comprendre les hooks de cycle de vie Vue.js


      Introduction

      Les hooks de cycle de vie apparaissent sous la forme d’une fenêtre dans laquelle vous pouvez voir de quelle manière la bibliothèque que vous utilisez fonctionne en arrière-plan. Ils vous permettent de savoir à quel moment votre composant est créé, ajouté au DOM, mis à jour ou détruit.

      Ce schéma, tiré de la documentation officielle de Vue.js, représente le cycle de vie de l’instance Vue.js :

      Schéma du cycle de vie de Vue.js

      Cet article est une introduction aux hooks de création, de compilation, de mise à jour et de destruction.

      Comprendre les hooks de création (initialisation)

      Les hooks de création sont les tous premiers à s’exécuter dans votre composant. Ils vous permettent de réaliser des actions avant même que votre composant n’ait été ajouté au DOM. Contrairement aux autres, les hooks de création sont également exécutés lorsque le rendu est généré côté serveur.

      Vous pouvez les utiliser pour configurer certains éléments dans votre composant, que le rendu soit généré côté client ou côté serveur.

      À l’intérieur des hooks de création, vous n’aurez pas accès au DOM ou à l’élément de compilation cible (this.$el).

      beforeCreate

      Le hook beforeCreate s’exécute au moment même de l’initalisation de votre composant. data n’a pas été activé et les events n’ont pas encore été configurés :

      ExampleComponent.vue

      <script>
      export default {
        beforeCreate() {
          console.log('At this point, events and lifecycle have been initialized.')
        }
      }
      </script>
      

      Dans cet exemple, lorsque le hook beforeCreate est exécuté, ce fragment de code consigne le message suivant : Initialisation des événements et du cycle de vie.

      created

      Le hook created vous permet d’accéder aux data et events qui sont actifs. La compilation ou le rendu des modèles et du DOM virtuel n’ont pas encore été déclenchés :

      ExampleComponent.vue

      <template>
        <div ref="example-element">{{ propertyComputed }}</div>
      </template>
      
      <script>
      export default {
        data() {
          return {
            property: 'Example property.'
          }
        },
      
        computed: {
          propertyComputed() {
            return this.property
          }
        },
      
        created() {
          console.log('At this point, this.property is now reactive and propertyComputed will update.')
          this.property = 'Example property updated.'
        }
      }
      </script>
      

      Dans cet exemple, le fragment de code consigne que property est une Example property. Lorsque le hook created est exécuté, le message suivant est enregistré : this.property est maintenant réactive et propertyComputed sera mise à jour. Ensuite, la valeur sous property est remplacée par Example property updated.

      Plus tard dans le cycle de vie, {{propertyComputed }} indiquera Example property updated au lieu de Example property.

      Au cours de cette étape, vous avez examiné quelques exemples de hooks de création. Vous êtes maintenant prêt à passer à la prochaine étape du cycle de vie, la compilation de hooks.

      Comprendre les hooks de compilation (insertion DOM)

      Les hooks de compilation sont ceux qui sont généralement les plus utilisés. Ils vous permettent d’accéder à votre composant immédiatement avant et après avoir généré le premier rendu. Cependant, ils ne sont pas exécutés lors du rendu côté serveur.

      Vous pouvez utiliser les hooks de compilation pour accéder ou modifier le DOM de votre composant immédiatement avant ou après avoir généré le rendu initial.

      N’utilisez pas de hooks de compilation pour récupérer des données sur votre composant lors de son initialisation.

      Remarque : pour cela, utilisez plutôt created (ou created et activated pour les composants keep-alive), surtout si vous avez besoin de ces données pour le rendu côté serveur.

      beforeMount

      Le hook beforeMount s’exécute juste avant l’occurrence du rendu initial et une fois que les fonctions du modèle ou du rendu aient été compilées :

      ExampleComponent.vue

      <script>
      export default {
        beforeMount() {
          console.log(`At this point, vm.$el has not been created yet.`)
        }
      }
      </script>
      

      Dans cet exemple, lorsque le hook beforeMount est exécuté, ce fragment de code enregistrera le message suivant : vm.$el n'a pas encore été créé.

      mounted

      Le hook mounted vous permet d’avoir un total accès au composant réactif, aux modèles et au DOM rendu (via this.$el).

      Utilisez mounted pour modifier le DOM, notamment lors de l’intégration de bibliothèque hors Vue :

      ExampleComponent.vue

      <template>
        <div ref="example-element">Example component.</div>
      </template>
      
      <script>
      export default {
        mounted() {
          console.log(`At this point, vm.$el has been created and el has been replaced.`);
          console.log(this.$el.textContent) // Example component.
        }
      }
      </script>
      

      Dans notre exemple, lorsque le hook mounted est exécuté, ce fragment de code consigne le message suivant : Crée vm.$el pour remplacer el. Le message Ceci est un exemple de texte (this.$el.textContent) sera également enregistré.

      Au cours de cette section, vous avez exploré les cas d’utilisation de hooks de compilation. À l’étape suivante, vous allez aborder quelques exemples de hooks de mise à jour.

      Comprendre les hooks de mise à jour (Diff et Re-render)

      Les Updating hooks se déclenchnt à chaque fois qu’une propriété réactive utilisée par votre composant change ou que quelque chose d’autre vous pousse à le re-render. Ils vous permettent de vous hooker au cycle watch-compute-render de votre composant.

      Vous pouvez utiliser les hooks de mise à jour pour savoir à quel moment le rendu du composant est de nouveau déclenché, éventuellement en vue d’un débogage ou d’un profilage.

      N’utilisez pas la mise à jour de hooks pour déterminer à quel moment une propriété réactive de votre composant change. Utilisez plutôt computed properties ou watchers.

      beforeUpdate

      Le hook beforeUpdate s’exécute une fois que les données de votre composant changent et que le cycle de mise à jour commence, juste avant que le DOM n’ait été patché et n’ait généré un re-render.

      Utilisez beforeUpdate pour consulter le nouvel état de toute donnée réactive de votre composant avant que le rendu soit effectivement généré :

      ExampleComponent.vue

      <template>
        <div ref="example-element">{{counter}}</div>
      </template>
      
      <script>
      export default {
        data() {
          return {
            counter: 0
          }
        },
      
        created() {
          setInterval(() => {
            this.counter++
          }, 1000)
        },
      
        beforeUpdate() {
          console.log(`At this point, Virtual DOM has not re-rendered or patched yet.`)
          // Logs the counter value every second, before the DOM updates.
          console.log(this.counter)
        }
      }
      </script>
      

      Tout d’abord, sous counter, ce fragment de code enregistrera 0. Lorsque le hook created est exécuté, la valeur du counter incrémentera toutes les 1 000 ms. Lorsque le hook beforeUpdate est exécuté, ce fragment de code enregistrera le message suivant : DOM virtuel pas encore été rendu ou patché. et un numéro sera enregistré sous counter.

      updated

      L’exécution du hook updated se fait à chaque fois que les données concernant votre composant sont modifiées et que le DOM déclenche un re-render.

      Utilisez updated pour accéder au DOM une fois qu’une propriété ait été modifiée :

      ExampleComponent.vue

      <template>
        <div ref="example-element">{{counter}}</div>
      </template>
      
      <script>
      export default {
        data() {
          return {
            counter: 0
          }
        },
      
        created() {
          setInterval(() => {
            this.counter++
          }, 1000)
        },
      
        updated() {
          console.log(`At this point, Virtual DOM has re-rendered and patched.`)
          // Fired every second, should always be true
          console.log(+this.$refs['example-element'].textContent === this.counter)
        }
      }
      </script>
      

      Tout d’abord, sous counter, ce fragment de code enregistrera 0. Lorsque le hook created est exécuté, la valeur du counter incrémentera toutes les 1 000 ms. Lorsque le hook updated est exécuté, ce fragment de code consigne le message suivant : Nouveau rendu et patch du DOM virtuel. Et, étant donné que la valeur du rendu est égale à la valeur actuelle, la valeur booléenne de true est consignée.

      Maintenant que vous en savez davantage sur l’utilisation des hooks de mise à jour, nous pouvons aborder les hooks de destruction.

      Comprendre les hooks de destruction (Démontage)

      Les hooks de destruction vous permettent d’effectuer des actions lorsque votre composant est détruit. Vous pouvez par exemple procéder à son nettoyage ou à l’envoi d’analyses. Ils se déclenchent au moment où votre composant est détruit et supprimé du DOM.

      beforeDestroy

      Le déclenchement de beforeDestroy se fait juste avant le démontage. Votre composant sera toujours présent et totalement fonctionnel.

      Utilisez beforeDestroy pour nettoyer des événements ou des abonnements réactifs :

      ExampleComponent.vue

      <script>
      export default {
        data() {
          return {
            exampleLeakyProperty: 'This represents a property that will leak memory if not cleaned up.'
          }
        },
      
        beforeDestroy() {
          console.log(`At this point, watchers, child components, and event listeners have not been teared down yet.`)
          // Perform the teardown procedure for exampleLeakyProperty.
          // (In this case, effectively nothing)
          this.exampleLeakyProperty = null
          delete this.exampleLeakyProperty
        }
      }
      </script>
      

      Ce fragment de code consignera tout d’abord exampleLeakyProperty. Lorsque le hook beforeDestroy est exécuté, ce fragment de code enregistrera le message suivant : Les observateurs, composants enfants et écouteurs d'événements n'ont pas encore été éliminés. Ensuite, exampleLeakyProperty est supprimé.

      destroyed

      Une fois que vous aurez atteint votre hooker destroyed, il ne vous restera pratiquement plus rien à faire sur votre composant. Tout ce qui y était rattaché a été détruit.

      Utilisez destroyed pour procéder à un nettoyage de dernière minute ou signaler à un serveur distant que le composant a été détruit :

      ExampleComponent.vue

      <script>
      import ExampleAnalyticsService from './example-analytics-service'
      
      export default {
        destroyed() {
          console.log(`At this point, watchers, child components, and event listeners have been torn down.`)
          console.log(this)
          ExampleAnalyticsService.informService('Component destroyed.')
        }
      }
      </script>
      

      Dans un premier temps, ce fragment de code importera ExampleAnalyticsService. Lorsque le hook beforeDestroy est exécuté, ce fragment de code consignera le message suivant : Supprime les observateurs, composants enfant et écouteurs d'événements. Ce qui reste du composant sera consigné dans la console et ExampleAnalyticsService transmettra le message suivant :Détruit.

      Voilà, vous êtes arrivé à la fin votre révision générale sur les hooks de cycle de vie Vue.js.

      Autres hooks

      Il existe deux autres hooks : activated et deactivated. Ils sont dédiés aux composants keep-alive, un sujet qui n’entre pas dans le cadre de cet article.

      Il vous suffit de savoir qu’ils vous permettent de détecter à quel moment un composant enveloppé dans une balise <keep-alive></keep-alive> est activé ou désactivé. Vous pouvez les utiliser pour récupérer les données de votre composant ou gérer les changements d’état, car ils se comportent effectivement comme created et beforeDestroy sans avoir à reconstruire un composant dans son intégralité.

      Conclusion

      Dans cet article, vous avez abordé les différents hooks de cycle de vie disponibles dans le cycle de vie d’une instance Vue.js. Vous avez découvert différents cas d’utilisation de hooks de création, de compilation, de mise à jour et de destruction.

      Si vous souhaitez en savoir plus sur Vue.js, veuillez consulter notre page thématique Vue.js dans laquelle vous trouverez des exercices et des projets de programmation.



      Source link

      How To Manage State with Hooks on React Components


      The author selected Creative Commons to receive a donation as part of the Write for DOnations program.

      Introduction

      In React development, keeping track of how your application data changes over time is called state management. By managing the state of your application, you will be able to make dynamic apps that respond to user input. There are many methods of managing state in React, including class-based state management and third-party libraries like Redux. In this tutorial, you’ll manage state on functional components using a method encouraged by the official React documentation: Hooks.

      Hooks are a broad set of tools that run custom functions when a component’s props change. Since this method of state management doesn’t require you to use classes, developers can use Hooks to write shorter, more readable code that is easy to share and maintain. One of the main differences between Hooks and class-based state management is that there is no single object that holds all of the state. Instead, you can break up state into multiple pieces that you can update independently.

      Throughout this tutorial, you’ll learn how to set state using the useState and useReducer Hooks. The useState Hook is valuable when setting a value without referencing the current state; the useReducer Hook is useful when you need to reference a previous value or when you have different actions the require complex data manipulations. To explore these different ways of setting state, you’ll create a product page component with a shopping cart that you’ll update by adding purchases from a list of options. By the end of this tutorial, you’ll be comfortable managing state in a functional component using Hooks, and you’ll have a foundation for more advanced Hooks such as useEffect, useMemo, and useContext.

      Prerequisites

      Step 1 – Setting Initial State in a Component

      In this step, you’ll set the initial state on a component by assigning the initial state to a custom variable using the useState Hook. To explore Hooks, you’ll make a product page with a shopping cart, then display the initial values based on the state. By the end of the step, you’ll know the different ways to hold a state value using Hooks and when to use state rather than a prop or a static value.

      Start by creating a directory for a Product component:

      • mkdir src/components/Product

      Next, open up a file called Product.js in the Product directory:

      • nano src/components/Product/Product.js

      Start by creating a component with no state. The component will consist of two parts: the cart, which has the number of items and the total price, and the product, which has a button to add or remove the item from the cart. For now, these buttons will have no function.

      Add the following code to the file:

      hooks-tutorial/src/components/Product/Product.js

      import React from 'react';
      import './Product.css';
      
      export default function Product() {
        return(
          <div className="wrapper">
            <div>
              Shopping Cart: 0 total items.
            </div>
            <div>Total: 0</div>
      
            <div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
            <button>Add</button> <button>Remove</button>
          </div>
        )
      }
      

      In this code, you used JSX to create the HTML elements for the Product component, with an ice cream emoji to represent the product. In addition, two of the <div> elements have class names so you can add some basic CSS styling.

      Save and close the file, then create a new file called Product.css in the Product directory:

      • nano src/components/Product/Product.css

      Add some styling to increase the font size for the text and the emoji:

      hooks-tutorial/src/components/Product/Product.css

      .product span {
          font-size: 100px;
      }
      
      .wrapper {
          padding: 20px;
          font-size: 20px;
      }
      
      .wrapper button {
          font-size: 20px;
          background: none;
          border: black solid 1px;
      }
      

      The emoji will need a much larger font-size, since it’s acting as the product image. In addition, you are removing the default gradient background on the button by setting background to none.

      Save and close the file. Now, add the component into the App component to render the Product component in the browser. Open App.js:

      • nano src/components/App/App.js

      Import the component and render it. Also, delete the CSS import since you won’t be using it in this tutorial:

      hooks-tutorial/src/components/App/App.js

      import React from 'react';
      import Product from '../Product/Product';
      
      function App() {
        return <Product />
      }
      
      export default App;
      

      Save and close the file. When you do, the browser will refresh and you’ll see the Product component:

      Product Page

      Now that you have a working component, you can replace the hard-coded data with dynamic values.

      React exports several Hooks that you can import directly from the main React package. By convention, React Hooks start with the word use, such as useState, useContext, and useReducer. Most third-party libraries follow the same convention. For example, Redux has a useSelector and a useStore Hook.

      Hooks are functions that let you run actions as part of the React lifecycle. Hooks are triggered either by other actions or by changes in a component’s props and are used to either create data or to trigger further changes. For example, the useState Hook generates a stateful piece of data along with a function for changing that piece of data and triggering a re-render. It will create a dynamic piece of code and hook into the lifecycle by triggering re-renders when the data changes. In practice, that means you can store dynamic pieces of data in variables using the useState Hook.

      For example, in this component, you have two pieces of data that will change based on user actions: the cart and the total cost. Each of these can be stored in state using the above Hook.

      To try this out, open up Product.js:

      • nano src/components/Product/Product.js

      Next, import the useState Hook from React by adding the highlighted code:

      hooks-tutorial/src/components/Product/Product.js

      import React, { useState } from 'react';
      import './Product.css';
      
      export default function Product() {
        return(
          <div className="wrapper">
            <div>
              Shopping Cart: 0 total items.
            </div>
            <div>Total: 0</div>
      
            <div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
            <button>Add</button> <button>Remove</button>
          </div>
        )
      }
      

      useState is a function that takes the initial state as an argument and returns an array with two items. The first item is a variable containing the state, which you will often use in your JSX. The second item in the array is a function that will update the state. Since React returns the data as an array, you can use destructuring to assign the values to any variable names you want. That means you can call useState many times and never have to worry about name conflicts, since you can assign every piece of state and update function to a clearly named variable.

      Create your first Hook by invoking the useState Hook with an empty array. Add in the following highlighted code:

      hooks-tutorial/src/components/Product/Product.js

      import React, { useState } from 'react';
      import './Product.css';
      
      export default function Product() {
        const [cart, setCart] = useState([]);
        return(
          <div className="wrapper">
            <div>
              Shopping Cart: {cart.length} total items.
            </div>
            <div>Total: 0</div>
      
            <div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
            <button>Add</button> <button>Remove</button>
          </div>
        )
      }
      

      Here you assigned the first value, the state, to a variable called cart. cart will be an array that contains the products in the cart. By passing an empty array as an argument to useState, you set the initial empty state as the first value of cart.

      In addition to the cart variable, you assigned the update function to a variable called setCart. At this point, you aren’t using the setCart function, and you may see a warning about having an unused variable. Ignore this warning for now; in the next step, you’ll use setCart to update the cart state.

      Save the file. When the browser reloads, you’ll see the page without changes:

      Product Page

      One important difference between Hooks and class-based state management is that, in class-based state management, there is a single state object. With Hooks, state objects are completely independent of each other, so you can have as many state objects as you want. That means that if you want a new piece of stateful data, all you need to do is call useState with a new default and assign the result to new variables.

      Inside Product.js, try this out by creating a new piece of state to hold the total. Set the default value to 0 and assign the value and function to total and setTotal:

      hooks-tutorial/src/components/Product/Product.js

      import React, { useState } from 'react';
      import './Product.css';
      
      export default function Product() {
        const [cart, setCart] = useState([]);
        const [total, setTotal] = useState(0);
        return(
          <div className="wrapper">
            <div>
              Shopping Cart: {cart.length} total items.
            </div>
            <div>Total: {total}</div>
      
            <div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
            <button>Add</button> <button>Remove</button>
          </div>
        )
      }
      

      Now that you have some stateful data, you can standardize the displayed data to make a more predictable experience. For example, since the total in this example is a price, it will always have two decimal places. You can use the toLocaleString method to convert total from a number to a string with two decimal places. It will also convert the number to a string according to the numerical conventions that match the browser’s locale. You’ll set the options minimumFractionDigits and maximumFractionDigits to give a consistent number of decimal places.

      Create a function called getTotal. This function will use the in-scope variable total and return a localized string that you will use to display the total. Use undefined as the first argument to toLocaleString to use the system locale rather than specifying a locale:

      hooks-tutorial/src/components/Product/Product.js

      import React, { useState } from 'react';
      import './Product.css';
      
      const currencyOptions = {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2,
      }
      
      export default function Product() {
        const [cart, setCart] = useState([]);
        const [total, setTotal] = useState(0);
      
        function getTotal() {
          return total.toLocaleString(undefined, currencyOptions)
        }
      
        return(
          <div className="wrapper">
            <div>
              Shopping Cart: {cart.length} total items.
            </div>
            <div>Total: {getTotal()}</div>
      
            <div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
            <button>Add</button> <button>Remove</button>
          </div>
        )
      }
      

      You now have added some string processing to the displayed total. Even though getTotal is a separate function, it shares the same scope as the surrounding function, which means it can reference the variables of the component.

      Save the file. The page will reload and you’ll see the updated total with two decimal places:

      Price converted to decimal

      This function works, but as of now, getTotal can only operate in this piece of code. In this case, you can convert it to a pure function, which gives the same outputs when given the same inputs and does not rely on a specific environment to operate. By converting the function to a pure function, you make it more reusable. You can, for example, extract it to a separate file and use it in multiple components.

      Update getTotal to take total as an argument. Then move the function outside of the component:

      hooks-tutorial/src/components/Product/Product.js

      import React, { useState } from 'react';
      import './Product.css';
      
      const currencyOptions = {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2,
      }
      
      function getTotal(total) {
        return total.toLocaleString(undefined, currencyOptions)
      }
      
      export default function Product() {
        const [cart, setCart] = useState([]);
        const [total, setTotal] = useState(0);
      
      
        return(
          <div className="wrapper">
            <div>
              Shopping Cart: {cart.length} total items.
            </div>
            <div>Total: {getTotal(total)}</div><^>
      
            <div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
            <button>Add</button> <button>Remove</button>
          </div>
        )
      }
      

      Save the file. When you do, the page will reload and you’ll see the component as it was before.

      Functional components like this make it easier to move functions around. As long as there are no scope conflicts, you can move these conversion functions anywhere you want.

      In this step, you set the default value for a stateful piece of data using useState. You then saved the stateful data and a function for updating the state to variables using array destructuring. In the next step, you’ll use the update function to change the state value to re-render the page with updated information.

      Step 2 — Setting State with useState

      In this step, you’ll update your product page by setting a new state with a static value. You have already created the function to update a piece of state, so now you’ll create an event to update both stateful variables with predefined values. By the end of this step, you’ll have a page with state that a user will be able to update at the click of a button.

      Unlike class-based components, you cannot update several pieces of state with a single function call. Instead, you must call each function individually. This means there is a greater separation of concerns, which helps keep stateful objects focused.

      Create a function to add an item to the cart and update the total with the price of the item, then add that functionality to the Add button:

      hooks-tutorial/src/components/Product/Product.js

      import React, { useState } from 'react';
      
      ...
      
      export default function Product() {
        const [cart, setCart] = useState([]);
        const [total, setTotal] = useState(0);
      
        function add() {
          setCart(['ice cream']);
          setTotal(5);
        }
      
        return(
          <div className="wrapper">
            <div>
              Shopping Cart: {cart.length} total items.
            </div>
            <div>Total: {getTotal(total)}</div>
      
            <div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
            <button onClick={add}>Add</button><^>
            <button>Remove</button>
          </div>
        )
      }
      

      In this snippet, you called setCart with an array containing the word “ice cream” and called setTotal with 5. You then added this function to the onClick event handler for the Add button.

      Notice that the function must have the same scope as the functions to set state, so it must be defined inside the component function.

      Save the file. When you do, the browser will reload, and when you click on the Add button the cart will update with the current amount:

      Click on the button and see state updated

      Since you are not referencing a this context, you can use either an arrow function or a function declaration. They both work equally well here, and each developer or team can decide which style to use. You can even skip defining an extra function and pass the function directly into the onClick property.

      To try this out, create a function to remove the values by setting the cart to an empty object and the total to 0. Create the function in the onClick prop of the Remove button:

      hooks-tutorial/src/component/Product/Product.js

      import React, { useState } from 'react';
      ...
      export default function Product() {
        const [cart, setCart] = useState([]);
        const [total, setTotal] = useState(0);
      
        function add() {
          setCart(['ice cream']);
          setTotal(5);
        }
      
        return(
          <div className="wrapper">
            <div>
              Shopping Cart: {cart.length} total items.
            </div>
            <div>Total: {getTotal(total)}</div>
      
            <div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
            <button onClick={add}>Add</button>
            <button
              onClick={() => {
                setCart([]);
                setTotal(0);
              }}
            >
              Remove
            </button>
          </div>
        )
      }
      

      Save the file. When you do, you will be able to add and remove an item:

      Add and Remove

      Both strategies for assigning the function work, but there are some slight performance implications to creating an arrow function directly in a prop. In every re-render, React will create a new function, which would trigger a prop change and cause the component to re-render. When you define a function outside of a prop, you can take advantage of another Hook called useCallback. This will memoize the function, meaning that it will only create a new function if certain values change. If nothing changes, the program will use the cached memory of the function instead of recalculating it. Some components may not need that level of optimization, but as a rule, the higher a component is likely to be in a tree, the greater the need for memoization.

      In this step, you updated state data with functions created by the useState Hook. You created wrapping functions to call both functions to update the state of several pieces of data at the same time. But these functions are limited because they add static, pre-defined values instead of using the previous state to create the new state. In the next step, you’ll update the state using the current state with both the useState Hook and a new Hook called useReducer.

      Step 3 — Setting State Using Current State

      In the previous step, you updated state with a static value. It didn’t matter what was in the previous state—you always passed the same value. But a typical product page will have many items that you can add to a cart, and you’ll want to be able to update the cart while preserving the previous items.

      In this step, you’ll update the state using the current state. You’ll expand your product page to include several products and you’ll create functions that update the cart and the total based on the current values. To update the values, you’ll use both the useState Hook and a new Hook called useReducer.

      Since React may optimize code by calling actions asynchronously, you’ll want to make sure that your function has access to the most up-to-date state. The most basic way to solve this problem is to pass a function to the state-setting function instead of a value. In other words, instead of calling setState(5), you’d call setState(previous => previous +5).

      To start implementing this, add some more items to the product page by making a products array of objects, then remove the event handlers from the Add and Remove buttons to make room for the refactoring:

      hooks-tutorial/src/component/Product/Product.js

      import React, { useState } from 'react';
      import './Product.css';
      
      ...
      
      const products = [
        {
          emoji: '🍦',
          name: 'ice cream',
          price: 5
        },
        {
          emoji: '🍩',
          name: 'donuts',
          price: 2.5,
        },
        {
          emoji: '🍉',
          name: 'watermelon',
          price: 4
        }
      ];
      
      export default function Product() {
        const [cart, setCart] = useState([]);
        const [total, setTotal] = useState(0);
      
        function add() {
          setCart(['ice cream']);
          setTotal(5);
        }
      
        return(
          <div className="wrapper">
            <div>
              Shopping Cart: {cart.length} total items.
            </div>
            <div>Total: {getTotal(total)}</div>
              <div>
              {products.map(product => (
                <div key={product.name}>
                  <div className="product">
                    <span role="img" aria-label={product.name}>{product.emoji}</span>
                  </div>
                  <button>Add</button>
                  <button>Remove</button>
                </div>
              ))}
            <^></div><^
          </div>
        )
      }
      

      You now have some JSX that uses the .map method to iterate over the array and display the products.

      Save the file. When you do, the page will reload and you’ll see multiple products:

      Product list

      Currently, the buttons have no actions. Since you only want to add the specific product on click, you’ll need to pass the product as an argument to the add function. In the add function, instead of passing the new item directly to the setCart and setTotal functions, you’ll pass an anonymous function that takes the current state and returns a new updated value:

      hooks-tutorial/src/component/Product/Product.js

      import React, { useState } from 'react';
      import './Product.css';
      ...
      export default function Product() {
        const [cart, setCart] = useState([]);
        const [total, setTotal] = useState(0);
      
        function add(product) {
          setCart(current => [...current, product.name]);
          setTotal(current => current + product.price);
        }
      
        return(
          <div className="wrapper">
            <div>
              Shopping Cart: {cart.length} total items.
            </div>
            <div>Total: {getTotal(total)}</div>
      
            <div>
              {products.map(product => (
                <div key={product.name}>
                  <div className="product">
                    <span role="img" aria-label={product.name}>{product.emoji}</span>
                  </div>
                  <button onClick={() => add(product)}>Add</button>
                  <button>Remove</button>
                </div>
              ))}
            </div>
          </div>
        )
      }
      

      The anonymous function uses the most recent state—either cart or total—as an argument that you can use to create a new value. Take care, though, not to directly mutate state. Instead, when adding a new value to the cart you can add the new product to the state by spreading the current value and adding the new value onto the end.

      Save the file. When you do, the browser will reload and you’ll be able to add multiple products:

      Adding products

      There’s another Hook called useReducer that is specially designed to update the state based on the current state, in a manner similar to the .reduce array method. The useReducer Hook is similar to useState, but when you initialize the Hook, you pass in a function the Hook will run when you change the state along with the initial data. The function—referred to as the reducer—takes two arguments: the state and another argument. The other argument is what you will supply when you call the update function.

      Refactor the cart state to use the useReducer Hook. Create a funciton called cartReducer that takes the state and the product as arguments. Replace useState with useReducer, then pass the cartReducer function as the first argument and an empty array as the second argument, which will be the initial data:

      hooks-tutorial/src/component/Product/Product.js

      import React, { useReducer, useState } from 'react';
      
      ...
      
      function cartReducer(state, product) {
        return [...state, product]
      }
      
      export default function Product() {
        const [cart, setCart] = useReducer(cartReducer, []);
        const [total, setTotal] = useState(0);
      
        function add(product) {
          setCart(product.name);
          setTotal(current => current + product.price);
        }
      
        return(
      ...
        )
      }
      

      Now when you call setCart, pass in the product name instead of a function. When you call setCart, you will call the reducer function, and the product will be the second argument. You can make a similar change with the total state.

      Create a function called totalReducer that takes the current state and adds the new amount. Then replace useState with useReducer and pass the new value setCart instead of a function:

      hooks-tutorial/src/component/Product/Product.js

      import React, { useReducer } from 'react';
      
      ...
      
      function totalReducer(state, price) {
        return state + price;
      }
      
      export default function Product() {
        const [cart, setCart] = useReducer(cartReducer, []);
        const [total, setTotal] = useReducer(totalReducer, 0);
      
        function add(product) {
          setCart(product.name);
          setTotal(product.price);
        }
      
        return(
          ...
        )
      }
      

      Since you are no longer using the useState Hook, you removed it from the import.

      Save the file. When you do, the page will reload and you’ll be able to add items to the cart:

      Adding products

      Now it’s time to add the remove function. But this leads to a problem: The reducer functions can handle adding items and updating totals, but it’s not clear how it will be able to handle removing items from the state. A common pattern in reducer functions is to pass an object as the second argument that contains the name of the action and the data for the action. Inside the reducer, you can then update the total based on the action. In this case, you will add items to the cart on an add action and remove them on a remove action.

      Start with the totalReducer. Update the function to take an action as the second argument, then add a conditional to update the state based on the action.type:

      hooks-tutorial/src/component/Product/Product.js

      import React, { useReducer } from 'react';
      import './Product.css';
      
      ...
      
      function totalReducer(state, action) {
        if(action.type === 'add') {
          return state + action.price;
        }
        return state - action.price
      }
      
      export default function Product() {
        const [cart, setCart] = useReducer(cartReducer, []);
        const [total, setTotal] = useReducer(totalReducer, 0);
      
        function add(product) {
          const { name, price } = product;
          setCart(name);
          setTotal({ price, type: 'add' });
        }
      
        return(
          ...
        )
      }
      

      The action is an object with two properites: type and price. The type can be either add or remove, and the price is a number. If the type is add, it increases the total. If it is remove, it lowers the total. After updating the totalReducer, you call setTotal with a type of add and the price, which you set using destructuring assignment.

      Next, you will update the cartReducer. This one is a little more complicated: You can use if/then conditionals, but it’s more common to use a switch statement. Switch statements are particularly useful if you have a reducer that can handle many different actions because it makes those actions more readable in your code.

      As with the totalReducer, you’ll pass an object as the second item type and name properties. If the action is remove, update the state by splicing out the first instance of a product.

      After updating the cartReducer, create a remove function that calls setCart and setTotal with objects containing type: 'remove' and either the price or the name. Then use a switch statement to update the data based on the action type. Be sure to return the final state:

      hooks-tutorial/src/complicated/Product/Product.js

      import React, { useReducer } from 'react';
      import './Product.css';
      
      ...
      
      function cartReducer(state, action) {
        switch(action.type) {
          case 'add':
            return [...state, action.name];
          case 'remove':
            const update = [...state];
            update.splice(update.indexOf(action.name), 1);
            return update;
          default:
            return state;
        }
      }
      
      function totalReducer(state, action) {
        if(action.type === 'add') {
          return state + action.price;
        }
        return state - action.price
      }
      
      export default function Product() {
        const [cart, setCart] = useReducer(cartReducer, []);
        const [total, setTotal] = useReducer(totalReducer, 0);
      
        function add(product) {
          const { name, price } = product;
          setCart({ name, type: 'add' });
          setTotal({ price, type: 'add' });
        }
      
        function remove(product) {
          const { name, price } = product;
          setCart({ name, type: 'remove' });
          setTotal({ price, type: 'remove' });
        }
      
        return(
          <div className="wrapper">
            <div>
              Shopping Cart: {cart.length} total items.
            </div>
            <div>Total: {getTotal(total)}</div>
      
            <div>
              {products.map(product => (
                <div key={product.name}>
                  <div className="product">
                    <span role="img" aria-label={product.name}>{product.emoji}</span>
                  </div>
                  <button onClick={() => add(product)}>Add</button>
                  <button onClick={() => remove(product)}>Remove</button>
                </div>
              ))}
            </div>
          </div>
        )
      }
      

      As you work on your code, take care not to directly mutate the state in the reducer functions. Instead, make a copy before splicing out the object. Also note it is a best practice to add a default action on a switch statement in order to account for unforeseen edge cases. In this, case just return the object. Other options for the default are throwing an error or falling back to an action such as add or remove.

      After making the changes, save the file. When the browser refreshes, you’ll be able to add and remove items:

      Remove items

      There is still a subtle bug left in this product. In the remove method, you can subtract from a price even if the item is not in the cart. If you click Remove on the ice cream without adding it to your cart, your displayed total will be -5.00.

      You can fix this bug by checking that an item exists before you subtract it, but a more efficient way is to minimize the different pieces of state by only saving related data in one place. In other words, try to avoid double references to the same data, in this case, the product. Instead, store the raw data in one state variable—the whole product object—then perform the calculations using that data.

      Refactor the component so that the add() function passes the whole product to the reducer and the remove() function removes the whole object. The getTotal method will use the cart, and so you can delete the totalReducer function. Then you can pass the cart to getTotal(), which you can refactor to reduce the array to a single value:

      hooks-tutorial/src/component/Product/Product.js

      import React, { useReducer } from 'react';
      import './Product.css';
      
      const currencyOptions = {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2,
      }
      
      function getTotal(cart) {
        const total = cart.reduce((totalCost, item) => totalCost + item.price, 0);
        return total.toLocaleString(undefined, currencyOptions)
      }
      
      ...
      
      function cartReducer(state, action) {
        switch(action.type) {
          case 'add':
            return [...state, action.product];
          case 'remove':
            const productIndex = state.findIndex(item => item.name === action.product.name);
            if(productIndex < 0) {
              return state;
            }
            const update = [...state];
            update.splice(productIndex, 1)
            return update
          default:
            return state;
        }
      }
      
      export default function Product() {
        const [cart, setCart] = useReducer(cartReducer, []);
      
        function add(product) {
          setCart({ product, type: 'add' });
        }
      
        function remove(product) {
          setCart({ product, type: 'remove' });
        } 
      
        return(
          <div className="wrapper">
            <div>
              Shopping Cart: {cart.length} total items.
            </div>
            <div>Total: {getTotal(cart)}</div>
      
            <div>
              {products.map(product => (
                <div key={product.name}>
                  <div className="product">
                    <span role="img" aria-label={product.name}>{product.emoji}</span>
                  </div>
                  <button onClick={() => add(product)}>Add</button>
                  <button onClick={() => remove(product)}>Remove</button>
                </div>
              ))}
            </div>
          </div>
        )
      }
      

      Save the file. When you do, the browser will refresh and you’ll have your final cart:

      Add and remove products

      By using the useReducer Hook, you kept your main component body well-organized and legible, since the complex logic for parsing and splicing the array is outside of the component. You also could move the reducer outside the componet if you wanted to reuse it, or you can create a custom Hook to use across multiple components. You can make custom Hooks as functions surrounding basic Hooks, such as useState, useReducer, or useEffect.

      Hooks give you the chance to move the stateful logic in and out of the component, as opposed to classes, where you are generally bound to the component. This advantage can extend to other components as well. Since Hooks are functions, you can import them into multiple components rather then using inheritance or other complex forms of class composition.

      In this step, you learned to set state using the current state. You created a component that updated state using both the useState and the useReducer Hooks, and you refactored the component to different Hooks to prevent bugs and improve reusability.

      Conclusion

      Hooks were a major change to React that created a new way to share logic and update components without using classes. Now that you can create components using useState and useReducer, you have the tools to make complex projects that respond to users and dynamic information. You also have a foundation of knowledge that you can use to explore more complex Hooks or to create custom Hooks.

      If you would like to look at more React tutorials, check out our React Topic page, or return to the How To Code in React.js series page.



      Source link