React Hooks : les coupes profondes de l'intelligence des données PlatoBlockchain. Recherche verticale. Aï.

React Hooks : les coupes profondes

Les crochets sont des fonctions réutilisables. Ils vous permettent d'utiliser Etat et d'autres fonctionnalités (par exemple, les méthodes de cycle de vie, etc.) sans écrire de classe. Les fonctions de hook nous permettent de "raccrocher" le Cycle de vie de l'état de réaction en utilisant des composants fonctionnels, nous permettant de manipuler l'état de nos composants fonctionnels sans avoir besoin de les convertir en composants de classe.

Réagir crochets introduits de retour dans la version 16.8 et n'a cessé d'en ajouter depuis. Certains sont plus utilisés et populaires que d'autres, comme useEffect, useStateet une useContext crochets. Je ne doute pas que vous les ayez atteints si vous travaillez avec React.

Mais ce qui m'intéresse, ce sont les crochets React moins connus. Bien que tous les crochets React soient intéressants à leur manière, il y en a cinq que je veux vraiment vous montrer car ils peuvent ne pas apparaître dans votre travail quotidien - ou peut-être qu'ils le font et les connaître vous donne des super pouvoirs supplémentaires.

Table des matières

useReducer

La useReducer hook est un outil de gestion d'état comme les autres hooks. Plus précisément, il s'agit d'une alternative à la useState crochet.

Si vous utilisez le useReducer crochet pour changer deux ou plusieurs états (ou actions), vous n'aurez pas à manipuler ces états individuellement. Le crochet garde une trace de tous les états et les gère collectivement. En d'autres termes : il gère et restitue les changements d'état. Contrairement à la useState accrocher, useReducer est plus facile lorsqu'il s'agit de gérer de nombreux états dans des projets complexes.

Les cas d'utilisation

useReducer peut aider à réduire la complexité du travail avec plusieurs états. Utilisez-le lorsque vous avez besoin de suivre plusieurs états collectivement, car il vous permet de traiter la gestion des états et la logique de rendu d'un composant comme des préoccupations distinctes.

Syntaxe

useReducer accepte trois arguments, dont l'un est facultatif :

  • une fonction de réducteur
  • initialState
  • an init fonction (facultatif)
const [state, dispatch] = useReducer(reducer, initialState)
const [state, dispatch] = useReducer(reducer, initialState initFunction) // in the case where you initialize with the optional 3rd argument

Exemple

L'exemple suivant est une interface qui contient une entrée de texte, un compteur et un bouton. Interagir avec chaque élément met à jour l'état. Remarquez comment useReducer nous permet de définir plusieurs cas à la fois plutôt que de les configurer individuellement.

import { useReducer } from 'react';
const reducer = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 };
    case 'DECREMENT':
      return { ...state, count: state.count - 1 };
    case 'USER_INPUT':
      return { ...state, userInput: action.payload };
    case 'TOGGLE_COLOR':
      return { ...state, color: !state.color };
    default:
      throw new Error();
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, { count: 0, userInput: '', color: false })

  return (
    <main className="App, App-header" style={{ color: state.color ? '#000' : '#FF07FF'}}>
      <input style={{margin: '2rem'}}
        type="text"
        value={state.userInput}
        onChange={(e) => dispatch({ type: 'USER_INPUT', payload: e.target.value })}
      />
      <br /><br />
      <p style={{margin: '2rem'}} >{state.count}</p>
      <section style={{margin: '2rem'}}>
        <button  onClick={(() => dispatch({ type: 'DECREMENT' }))}>-</button>
        <button onClick={(() => dispatch({ type: 'INCREMENT' }))}>+</button>
        <button onClick={(() => dispatch({ type: 'TOGGLE_COLOR' }))}>Color</button>
      </section>
      <br /><br />
      <p style={{margin: '2rem'}}>{state.userInput}</p>
    </main>
  );
}
export default App;

À partir du code ci-dessus, remarqué comment nous sommes capables de gérer facilement plusieurs états dans le réducteur (switch-case), cela montre l'avantage de la useReducer. C'est la puissance qu'il donne lorsque vous travaillez dans des applications complexes avec plusieurs états.

useRef

La useRef hook est utilisé pour créer des références sur des éléments afin d'accéder au DOM. Mais plus que cela, il renvoie un objet avec un .current propriété qui peut être utilisée tout au long du cycle de vie d'un composant, permettant aux données de persister sans provoquer de nouveau rendu. Alors le useRef la valeur reste la même entre les rendus ; la mise à jour de la référence ne déclenche pas de nouveau rendu.

Les cas d'utilisation

Atteindre le useRef accroche quand tu veux :

  • Manipulez le DOM avec des informations modifiables stockées.
  • Accéder aux informations des composants enfants (éléments imbriqués).
  • Mettre le focus sur un élément.

Il est particulièrement utile lors du stockage de données mutables dans votre application sans provoquer de nouveau rendu.

Syntaxe

useRef n'accepte qu'un seul argument, qui est le valeur initiale.

const newRefComponent = useRef(initialValue);

Exemple

Ici, j'ai utilisé le useRef et de useState crochet pour afficher le nombre de fois qu'une application affiche un état mis à jour lors de la saisie d'une entrée de texte.

import './App.css'

function App() {
  const [anyInput, setAnyInput] = useState(" ");
  const showRender = useRef(0);
  const randomInput = useRef();
  const toggleChange = (e) => {
    setAnyInput (e.target.value);
    showRender.current++;
  
  }
  const focusRandomInput = () => {
    randomInput.current.focus();
  }

  return (
    <div className="App">
      <input className="TextBox" 
        ref ={randomInput} type="text" value={anyInput} onChange={toggleChange}
      />
      <h3>Amount Of Renders: {showRender.current}</h3>
      <button onClick={focusRandomInput}>Click To Focus On Input </button>
    </div>
  );
}

export default App;

Remarquez comment la saisie de chaque caractère dans le champ de texte met à jour l'état de l'application, mais ne déclenche jamais un nouveau rendu complet.

useImperativeHandle

Vous savez comment un composant enfant a accès aux fonctions d'appel qui lui sont transmises depuis le composant parent ? Les parents les transmettent via des accessoires, mais ce transfert est "unidirectionnel" dans le sens où le parent est incapable d'appeler une fonction qui se trouve dans l'enfant.

Eh bien, useImperativeHandle permet à un parent d'accéder aux fonctions d'un composant enfant.

Comment ça marche?

  • Une fonction est définie dans le composant enfant.
  • A ref est ajouté dans le parent.
  • Nous utilisons forwardRef, permettant le ref qui a été défini pour être transmis à l'enfant.
  • useImperativeHandle expose les fonctions de l'enfant via le ref.

Les cas d'utilisation

useImperativeHandle fonctionne bien lorsque vous souhaitez qu'un composant parent soit affecté par les modifications apportées à l'enfant. Ainsi, des choses comme une mise au point modifiée, une incrémentation et une décrémentation, et des éléments flous peuvent être des situations où vous vous retrouvez à atteindre ce crochet afin que le parent puisse être mis à jour en conséquence.

Syntaxe

useImperativeHandle (ref, createHandle, [dependencies])

Exemple

Dans cet exemple, nous avons deux boutons, l'un dans un composant parent et l'autre dans un enfant. Cliquer sur le bouton parent récupère les données de l'enfant, nous permettant de manipuler le composant parent. Il est configuré de sorte que cliquer sur le bouton enfant ne transmette rien du composant parent à l'enfant pour aider à illustrer comment nous passons les choses dans la direction opposée.

// Parent component
import React, { useRef } from "react";
import ChildComponent from "./childComponent";
import './App.css';

function useImperativeHandle() {
  const controlRef = useRef(null);
  return (
    onClick={
      () => {
        controlRef.current.controlPrint();
      }
    }
    >
    Parent Box
  );
}
export default useImperativeHandle;
// Child component
import React, { forwardRef, useImperativeHandle, useState } from "react";

const ChildComponent = forwardRef((props, ref) => {
  const [print, setPrint] = useState(false);
  useImperativeHandle(ref, () => ({
    controlPrint() 
    { setPrint(!print); },
  })
  );

  return (
    <>
    Child Box
    { print && I am from the child component }
  );
});

export default ChildComponent;

Sortie

useMemo

useMemo est l'un des crochets React les moins utilisés mais les plus intéressants. Cela peut améliorer les performances et réduire la latence, en particulier sur les calculs volumineux dans votre application. Comment? Chaque fois que l'état d'un composant est mis à jour et que les composants sont restitués, le useMemo hook empêche React d'avoir à recalculer les valeurs.

Vous voyez, les fonctions répondent aux changements d'état. La useMemo crochet prend une fonction et renvoie la valeur de retour de cette fonction. Il met cette valeur en cache pour éviter de dépenser des efforts supplémentaires pour la restituer, puis la renvoie lorsque l'une des dépendances a changé.

Ce processus s'appelle mémorisation et c'est ce qui aide à améliorer les performances en se souvenant de la valeur d'une requête précédente afin qu'elle puisse être réutilisée sans répéter tout ce calcul.

Les cas d'utilisation

Les meilleurs cas d'utilisation seront à chaque fois que vous travaillez avec des calculs lourds où vous souhaitez stocker la valeur et l'utiliser lors des changements d'état ultérieurs. Cela peut être une belle performance, mais l'utiliser trop peut avoir l'effet inverse en monopolisant la mémoire de votre application.

Syntaxe

useMemo( () => 
  { // Code goes here },
  []
)

Exemple

En cliquant sur le bouton, ce mini-programme indique quand un nombre est pair ou impair, puis met la valeur au carré. J'ai ajouté beaucoup de zéros à la boucle pour augmenter sa puissance de calcul. Il renvoie la valeur en secondes renversées et fonctionne toujours bien en raison de la useMemo crochet.

// UseMemo.js
import React, { useState, useMemo } from 'react'

function Memo() {
  const [memoOne, setMemoOne] = useState(0);
  const incrementMemoOne = () => { setMemoOne(memoOne + 1) }
  const isEven = useMemo(() => { 
    let i = 0 while (i < 2000000000) i++ return memoOne % 2 === 0
  },
  [memoOne]);
  
  const square = useMemo(()=> { 
    console.log("squared the number"); for(var i=0; i < 200000000; i++);
    return memoOne * memoOne;
  },
  [memoOne]);

  return (
    Memo One - 
    { memoOne }
    { isEven ? 'Even' : 'Odd' } { square } 
  );
}
export default Memo

Sortie

useMemo est un peu comme le useCallback crochet, mais la différence est que useMemo peut stocker une valeur mémorisée à partir d'une fonction, où useCallback stocke la fonction mémorisée elle-même.

useCallback

La useCallback crochet est un autre intéressant et la dernière section était une sorte d'alerte spoiler pour ce qu'il fait.

Comme nous venons de le voir, useCallback fonctionne comme le useMemo crochet en ce sens qu'ils utilisent tous les deux la mémorisation pour mettre en cache quelque chose pour une utilisation ultérieure. Alors que useMemo stocke le calcul d'une fonction sous forme de valeur en cache, useCallback stocke et renvoie une fonction.

Les cas d'utilisation

Comme useMemo, useCallback est une belle optimisation des performances dans la mesure où il stocke et renvoie un rappel mémorisé et l'une de ses dépendances sans re-rendu.

Syntaxe

const getMemoizedCallback = useCallback (
  () => { doSomething () }, []
);

Exemple


{ useCallback, useState } from "react";
import CallbackChild from "./UseCallback-Child";
import "./App.css"

export default function App() {
  const [toggle, setToggle] = useState(false);
  const [data, setData] = useState("I am a data that would not change at every render, thanks to the useCallback");
  const returnFunction = useCallback(
    (name) => 
    { return data + name; }, [data]
  );
  return (
    onClick={() => {
      setToggle(!toggle);
    }}
    >
    {" "}

    // Click To Toggle
    { toggle && h1. Toggling me no longer affects any function } 
  ); 
}
// The Child component
import React, { useEffect } from "react";

function CallbackChild(
  { returnFunction }
) {
  useEffect(() => 
    { console.log("FUNCTION WAS CALLED"); },
    [returnFunction]);
  return { returnFunction(" Hook!") };
}
export default CallbackChild;

Sortie

Réflexions finales

On y va ! Nous venons de regarder cinq crochets React super pratiques qui, je pense, sont souvent négligés. Comme pour de nombreuses rafles comme celle-ci, nous ne faisons qu'effleurer la surface de ces crochets. Ils ont chacun leurs propres nuances et considérations à prendre en compte lorsque vous les utilisez. Mais j'espère que vous avez une bonne idée de ce qu'ils sont et quand ils pourraient être mieux adaptés qu'un autre crochet que vous pourriez atteindre plus souvent.

La meilleure façon de bien les comprendre est par la pratique. Je vous encourage donc à vous entraîner à utiliser ces crochets dans votre application pour une meilleure compréhension. Pour cela, vous pouvez approfondir vos connaissances en consultant les ressources suivantes :

Horodatage:

Plus de Astuces CSS