Le hook : useState

Un Hook est une fonction qui permet d' « accocher » une des fonctionnalités React. à une fonction-composant.

Pour ajouter un état à une fonction-composant on utilise  le 'hook"  useState de React. Cela signifie qu'il faut l'importer

import React, { useState } from 'react';

Ensuite, on déclare l'état de la fonction- composant  par l'appel à useState()

Exemple : la fonction-composant Crud()

const Crud = () => {
 //déclaration de l'état du composant
    const [ studentName, setStudentName ]= useState("");
    const [ course, setCourse ]= useState("");
    const [ colore, setColoreBorderInputText ]= useState("blue");
  // ...
 return(
    <>
        <View style={styles.container, {backgroundColor:"lightcyan"}}>
         { Lire()}
         </View>
         <View style={styles.container , {backgroundColor:"lightcyan"}}>
         {Inscrire()}
        </View>
    </>
    )
};

L'appel de useState a trois effets:

  1. création et initialisation de variables(dites variables d'état pour mémoriser l'état de la fonction-composant : dans l'exemple ci-dessus, les variables  d'état sont "studentName", "course" et "colore" ;
  2. initialisation de la variable d'état avec la valeur du paramètre de useState(). Dans l'exemple la variable d'état "colore" est initialisée à "blue".
  3. création d'un setter : fonction qui met à jour la valeur la variable d'état créée. Dans l'exemple les setter sont "setStudentName", "setCourse" et "setColoreBorderInputText" ;

 

Attention cependant, chaque utilisation d'un setter (exemple : setStudentName)
  • mettra à jour sa variable d'état (dans l'exemple : studentName sera mis à jour) ;
  • provoquera un nouveau rendu ("re-chargement") de la fonction- composant.

React se rappelle de la valeur des variables d'état entre deux rendus et fournit toujours la plus récente à notre fonction-composant.

 

L'image ci-contre est une illustration de l'erreur produite par la fonction-composant Compteur dont le code est affiché ci-dessous.

Le problème : le setter setCount()  est invoquée lorsque le composant est rendu, il met à jour l'état, ce qui provoque un nouveau rendu. Celui-ci invoque donc le setter qui met à jour l'état, et qui provoque un nouveau rendu et cela boucle à l'infini.

Exemple de boucle infinie :

const Compteur = () => {
    const[ count, setCount] = useState(0);

    setCount((count) => count + 1);

    return (
        <View>
                <Text
                    style={{
                      justifyContent: 'center',
                      alignItems: 'center',
                      marginTop: 16,
                    }}
                >
                Compteur: {count}
                </Text>
        </View>
    )        
};

Dans l'exemple ci-dessous, il n'y plus de boucle infinie car le setter n'est appelé que si une condition est remplie.

const Compteur = () => {
    const[ count, setCount] = useState(0);

    let i = Math.random();
    console.log("re-render: " + i);
    if (i < 0.9) {
                console.log("un de plus");
                setCount (count + 1);
    };
    return (
        <View>
               <Text
                    style={{
                      justifyContent: 'center',
                      alignItems: 'center',
                      marginTop: 16,
                    }}
                >
                Compteur: {count}
                </Text>
        </View>
    )        
};

L'illustration ci-contre montre que 4 rendus se sont produits

  • le 1er au chargement de la page (re-render 0.74...) puis
  • parce que  0.74 <1, suite l'appel à setCount  avec pour log re-render : 0.88 (après le log "un de plus" et count vaut 1)  puis
  • parce que  0.88 <1, suite l'appel à setCount  avec pour log re-render : 0.44 (après le log "un de plus"  et count vaut 2)  puis
  • parce que  0.44 <1, suite l'appel à setCount  avec pour log re-render : 0.95 (après le log "un de plus"  et count vaut 3).
  • puisque 0.95 >1, il n'y a plus d'appel à setCount et la fonction-composant peut rendre son résultat : count = 3

Ci-dessous figure le code de la fonction "Inscrire".

Les contrôles "TextInput" utilisent les 3 setters pour:

  • mémoriser un nom d'étudiant ;
  • mémoriser un cours ;
  • mémoriser une couleur

    const Inscrire =() => {
        return(
            <View>
                <View style={{width:"100%", backgroundColor:"coral",}}>
                    <Text style={{ textAlign:"center", fontWeight :"bold",fontSize:20 }}>
                        - Ajouter un enregistrement -
                    </Text>
                </View>
                <TextInput
                    style= { [styles.input, {borderColor:colore,width:220} ]}
                    placeholder={"nom de l'étudiant : "}
                    onChangeText={setStudentName}
                    value={studentName}
                    maxLength={24}
                    onFocus={colore => setColoreBorderInputText("red")}
                />
            <TextInput
                style= { [styles.input, {borderColor:colore,width:220} ]}
                placeholder={"nom du cours : "}
                onChangeText={setCourse}
                value={course}
                maxLength={24}
                onFocus={colore => setColoreBorderInputText("red")}
            />
            <View style= { {width:"50%", alignSelf:"center"} }>    
                <Button
                    style= {styles.button }
                    title={"Enregistrer"}
                    onPress={InsertRecord}
                />
            </View>
        </View>
    )}
}

Enfin une fonction "InsertRecord", présentée ici, permet d'enregistrer ces données dans une table d'une base de donnée.