157 votes

Comment utiliser React.forwardRef dans un composant basé sur une classe?

Je suis en train d'utiliser Réagir.forwardRef, mais trébuche sur la façon de l'obtenir pour fonctionner dans une classe de composant (non HOC).

Les docs des exemples d'utilisation d'éléments et de composants fonctionnels, même en enveloppant les classes de fonctions d'ordre supérieur composants.

Donc, commencer avec quelque chose comme cela dans leur ref.js le fichier:

const TextInput = React.forwardRef(
    (props, ref) => (<input type="text" placeholder="Hello World" ref={ref} />)
);

et au lieu de le définir comme quelque chose comme ceci:

class TextInput extends React.Component {
  render() {
    let { props, ref } = React.forwardRef((props, ref) => ({ props, ref }));
    return <input type="text" placeholder="Hello World" ref={ref} />;
  }
}

ou

class TextInput extends React.Component {
  render() { 
    return (
      React.forwardRef((props, ref) => (<input type="text" placeholder="Hello World" ref={ref} />))
    );
  }
}

seulement de travail :/

Aussi, je sais je sais, ref ne sont pas réagir de la sorte. Je suis en train d'utiliser un tiers de la toile de la bibliothèque, et souhaitez ajouter certains de leurs outils dans des composants distincts, donc j'ai besoin d'écouteurs d'événement, donc j'ai besoin du cycle de vie des méthodes. Il peut aller dans une autre route plus tard, mais je veux essayer cette.

Les docs disent que c'est possible!

Ref transfert n'est pas limité à DOM composants. Vous pouvez transférer les références à la classe des instances de composants, trop.

à partir de la note dans la présente section.

Mais ensuite, ils vont à l'utilisation HOCs au lieu de simplement les classes.

175voto

Mr Br Points 213

L'idée de toujours utiliser le même accessoire pour le ref peut être réalisée en procurant une exportation de classe par proxy avec un assistant.

 class ElemComponent extends Component {
  render() {
    return (
      <div ref={this.props.innerRef}>
        Div has ref
      </div>
    )
  }
}

export default React.forwardRef((props, ref) => <ElemComponent 
  innerRef={ref} {...props}
/>);
 

Donc, fondamentalement, oui, nous sommes obligés d'avoir un accessoire différent pour transmettre la référence, mais cela peut être fait sous le moyeu. Il est important que le public l'utilise comme référence normale.

18voto

Sebastien Lorber Points 9682
 class BeautifulInput extends React.Component {
  const { innerRef, ...props } = this.props;
  render() (
    return (
      <div style={{backgroundColor: "blue"}}>
        <input ref={innerRef} {...props} />
      </div>
    )
  )
}

const BeautifulInputForwardingRef = React.forwardRef((props, ref) => (
  <BeautifulInput {...props} innerRef={ref}/>
));

const App = () => (
  <BeautifulInputForwardingRef ref={ref => ref && ref.focus()} />
)
 

Vous devez utiliser un nom d'accessoire différent pour transmettre la référence à une classe. innerRef est couramment utilisé dans de nombreuses bibliothèques.

12voto

Fondamentalement, ce n'est qu'une fonction HOC. Si vous vouliez l'utiliser avec la classe, vous pouvez le faire vous-même et utiliser des accessoires réguliers.

 class TextInput extends React.Component {
    render() {
        <input ref={this.props.forwardRef} />
    }
}

const ref = React.createRef();
<TextInput forwardRef={ref} />
 

Ce modèle est utilisé par exemple dans styled-components et il s'appelle innerRef là-bas.

7voto

rpearce Points 496

Cela peut être accompli avec un composant d'ordre supérieur, si vous le souhaitez:

 import React, { forwardRef } from 'react'

const withForwardedRef = Comp => {
  const handle = (props, ref) =>
    <Comp {...props} forwardedRef={ref} />

  const name = Comp.displayName || Comp.name
  handle.displayName = `withForwardedRef(${name})`

  return forwardRef(handle)
}

export default withForwardedRef
 

Et puis dans votre fichier composant:

 class Boop extends React.Component {
  render() {
    const { forwardedRef } = this.props

    return (
      <div ref={forwardedRef} />
    )
  }
}

export default withForwardedRef(Boop)
 

J'ai fait le travail à l'avance avec des tests et publié un package pour cela, react-with-forwarded-ref : https://www.npmjs.com/package/react-with-forwarded-ref

5voto

orepor Points 653

Dans le cas où vous devez réutiliser cela dans de nombreux composants différents, vous pouvez exporter cette capacité vers quelque chose comme withForwardingRef

 const withForwardingRef = <Props extends {[_: string]: any}>(BaseComponent: React.ReactType<Props>) =>
    React.forwardRef((props, ref) => <BaseComponent {...props} forwardedRef={ref} />);

export default withForwardingRef;
 

usage:

 const Comp = ({forwardedRef}) => (
 <input ref={forwardedRef} />
)
const EnhanceComponent = withForwardingRef<Props>(Comp);  // Now Comp has a prop called forwardedRef
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X