L'utilisation de ref dans React (composants de classe et composants de fonction) et une explication détaillée de forwardRef et useImperativeHandle

avant-propos

Dans un composant parent, nous souhaitons y obtenir l'élément de nœud ou l'instance du composant enfant, afin d'appeler directement la méthode dessus. Les composants de classe et les composants de fonction sont deux manières différentes d'écrire.

1. Utilisez ref dans le composant Class

Dans le composant Class de React, nous createRefcréons ref par

class Parent extends React.Component {
    
    
    constructor(props) {
    
    
        super(props)
        this.inputRef = React.createRef();
    }
    
    componentDidMount() {
    
    
        console.log(this.inputRef)
        this.inputRef.current.focus();
    }
    render() {
    
    
        return <input ref={
    
    this.inputRef} />
    }
}

Dans l'exemple de code ci-dessus, nous avions l'habitude d' createRefen créer un refet de l'accrocher à l'entrée de l'élément DOM natif. À ce stade, nous pouvons ref.currentfaire passer cet élément DOM et appeler la méthode ci-dessus.

Si ref est monté sur un composant Class, ref.current obtient l'instance du composant Class et peut également accéder aux méthodes du composant Class.

[Le transfert d'image par lien externe a échoué, le site source peut avoir un mécanisme anti-sangsue, il est recommandé de sauvegarder l'image et de la télécharger directement (img-mhBeu0cR-1669790444660) (C:\Users\Two Three\AppData\Roaming\Typora \ typora-user-images \ image-20221130102359179.png)]

Prenons la page ci-dessus comme exemple, le [Plan de dessin] suivant est un sous-composant, lorsque nous montons refsur le sous-composant, le composant parent correspondant peut this.ref.currentappeler la méthode sur le sous-composant, comme la liste déroulante pour développer les rappels, les rappels pour les modifications de valeur de la liste déroulante, etc.

2. Composants fonctionnels

ref 回调函数Une fois le composant monté,l'instance du composant sera transmise à la fonction.Le composant fonction est différent du composant Class et le composant fonction n'a pas d'instance . Ainsi, dans des circonstances normales, la référence ne peut pas être montée sur des composants fonctionnels.

Cependant, les composants de fonction peuvent créer des références. Contrairement aux composants de classe, les composants de fonction utilisent useRef.

import React, {
    
     memo, useEffect,  useRef, useState } from 'react';
const Parent = () => {
    
    
    const inputRef = useRef(null)
    input childRef = useRef(null)
    
    return (
        <>
        	<input ref={
    
    inputRef} onChange={
    
    onChange} />
        	<Child ref={
    
    childRef} handSave={
    
    handSave} />
        </>
    )
}

export default memo(Parent)

Remarque : Cette façon d'écrire est grammaticalement correcte, mais si vous souhaitez ref.currentobtenir une instance d'un élément ou d'un sous-composant DOM dans un composant de fonction, vous ne pouvez pas l'obtenir et vous avez besoin d'une autre façon d'écrire.

3. La différence entre createRef et useRef

  • createRef ne peut être utilisé que dans les composants de classe Class et useRef ne peut être utilisé que dans les composants fonctionnels.
  • createRef renvoie une nouvelle référence à chaque rendu, useRef renvoie la même référence à chaque fois.
  • Si la référence créée par createRef est utilisée dans un composant fonctionnel, sa valeur sera continuellement initialisée au fur et à mesure de la réexécution du composant fonctionnel .

4. Conclusions partielles

En résumé, les points suivants peuvent être résumés :

  • Élément DOM natif : le courant de ref pointe vers ce nœud
  • composant de classe de classe : le courant de la référence pointe vers l'instance du composant
  • Composant fonctionnel : le courant de ref pointe vers null, car le composant fonctionnel n'a pas d'instance.

Donc, pour les composants fonctionnels, n'y a-t-il vraiment aucun moyen pour nous d'obtenir et d'appeler les méthodes sur les sous-composants ?

Réponse : Comment est-ce possible, nous pouvons forwardRefrésoudre ce problème en utilisant .

5. forwardRef

forwardRef (passage par référence) est une technique permettant de transmettre automatiquement une référence de référence d'un composant à un composant enfant.

En une phrase : React utilise forwardRef pour terminer la transmission transparente de ref, afin que les composants fonctionnels puissent normalement obtenir les méthodes sur les sous-composants.

5.1 Écriture du code

import React, {
    
     memo, forwardRef,  useRef, useImperativeHandle } from 'react';

const App = () => {
    
    
    const childRef = useRef(null)
    
    const getFocus = () => {
    
    
         // 调用子组件的方法
        childRef.current.inputFocus()
        // 也可以调用暴露出来的其他值
        childRef.current.setData(20)
    }
    
    return (
        <>
        	<Child ref={
    
    childRef}/>
        	<button onClick ={
    
    getFocus}>点击获取焦点<button/>
        </>
    )
}

// 子组件

const Child = forwardRef((props, ref) => {
    
    
    const inputRef = useRef(null)
    const [data, setData] = useState('10')
    
    // 使输入框获取焦点的方法
    const inputFocus = () => {
    
    
        inputRef.current.ocus()
    }
    // 输入框内容改变回调
    const changeValue = () => {
    
    
    	console.log('哈哈哈')
    }
    
    // 将该方法暴露给父组件
    useImperativeHandle(ref, () => ({
    
    
        inputFocus,
        changeValue,
        data,
        setData
    }))
    
    return <input  ref={
    
    inputRef} onChange={
    
    changeValue}>
});

5.2 Analyse forwardRef

forwardRef Vous pouvez directement encapsuler un composant fonctionnel , et le composant fonctionnel encapsulé se verra attribuer la référence (en tant que deuxième paramètre). Si vous attribuez directement ref à un composant fonctionnel qui n'est pas encapsulé par forwardRef, React signalera une erreur dans la console.

forwardRefUn composant React sera créé, qui pourra transmettre l'attribut ref qu'il accepte à un autre composant sous son arborescence de composants, c'est-à-dire une transmission transparente.

Remarque : le paramètre de forWardRef doit être une fonction

6. useImperativeHandleAnalyse

Lorsqu'il est utilisé directement forwardRef, nous ne pouvons pas contrôler la valeur à exposer au composant parent, nous l'utilisons donc pour useImperativeHandlecontrôler ce qu'il faut exposer au composant parent.

Remarque : useImperativeHandle doit être utilisé avec forwardRef.

La méthode d'appel est affichée dans l'exemple de code ci-dessus.

6.1 Passage de paramètres

  • Le premier paramètre : ref : Reçoit la référence transmise par forwardRef.
  • Le deuxième paramètre : createHandle : Fonction de gestion, la valeur de retour est exposée en tant qu'objet ref au composant parent.
  • Le troisième paramètre : deps : dépendances deps, les modifications de dépendance forment un nouvel objet ref, ne peuvent pas être transmises

useImperativeHandle nous fournit un élément semblable à une instance qui nous aide à monter le contenu de l'objet renvoyé sur la référence actuelle de la pièce jointe via le deuxième paramètre de useImperativeHandle.

7. Résumé

Les étapes lorsque les composants parent et enfant utilisent les hooks sont les suivantes :

  1. Le composant parent utilise pour useRefcréer un objet ref et affecter cet objet ref à la propriété ref du composant enfant.
  2. Le composant enfant s'enveloppe forwardReflui-même avec un , permettant à la référence d'être utilisée comme composant de fonction lui-même. Utilisez ensuite useImperativeHandlela fonction hook pour renvoyer un état ou une méthode dans le deuxième paramètre de fonction de la fonction hook, et l'état ou la méthode renvoyée est accessible par le composant parent.
  3. Le composant parent utilise la propriété de l'objet ref créé currentpour obtenir l'état ou la méthode exposée par le composant enfant.

8. Points d'attention particuliers :

forwardRef Lors de l'utilisation et dans les composants fonctionnels useImperativeHandle, il y a un point particulier qui mérite une attention particulière : la méthode de transmission des paramètres dans les sous-composants . Comme suit:

// 可以使用这样的写法
    <Child ref={
    
    childRef} list={
    
    drawingPlanList} editable={
    
    !isDisabled}/>

// 但不用采用这样的写法:这样的 写法有问题,具体原因待排查

	const childProps = {
    
    
		ref: {
    
    childRef},
		list: {
    
    drawingPlanList},
		editable: {
    
    !isDisabled}
	}
    < Child {
    
    ...childProps}/>

Je suppose que tu aimes

Origine blog.csdn.net/qq_41131745/article/details/128114965
conseillé
Classement