web-dev-qa-db-fra.com

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

J'essaie d'utiliser React.forwardRef, mais je commence à comprendre comment le faire fonctionner dans un composant basé sur une classe (pas HOC).

Les exemples de documentation utilisent des éléments et des composants fonctionnels, même en encapsulant des classes dans des fonctions pour des composants d'ordre supérieur.

Donc, en commençant par quelque chose comme this dans leur fichier ref.js:

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} />))
     );
    }
}

ne fonctionne que: /

De plus, je sais que je sais que les arbitres ne sont pas le moyen de réagir. J'essaie d'utiliser une bibliothèque de canevas tierce et j'aimerais ajouter certains de leurs outils dans des composants distincts. J'ai donc besoin d'écouteurs d'événements et de méthodes de cycle de vie. Il se peut que cela change plus tard, mais je veux essayer.

Les docs disent que c'est possible!

Le renvoi des références ne se limite pas aux composants DOM. Vous pouvez également transférer des références vers des instances de composant de classe.

de la note dans cette section.

Mais ensuite, ils utilisent des HOC plutôt que de simples classes.

38
Han Lazarus

L'idée de toujours utiliser le même accessoire pour la variable ref peut être réalisée en effectuant un proxy d'exportation de classe 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, nous sommes obligés d’avoir un accessoire différent pour transmettre les renvois, mais cela peut se faire sous le hub. Il est important que le public l'utilise comme référence normale. 

23
Mr Br
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 différent pour transférer la référence vers une classe. innerRef est couramment utilisé dans de nombreuses bibliothèques.

3
Sebastien Lorber

Fondamentalement, ceci est juste une fonction HOC. Si vous vouliez l'utiliser en 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.

3

Si vous avez besoin de le réutiliser 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
2
orepor

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

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 de composant:

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

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

export default withForwardedRef(Boop)

J'ai fait le travail en amont avec les tests et publié un paquet pour cela, react-with-forwarded-ref: https://www.npmjs.com/package/react-with-forwarded-ref

1
rpearce

C'est exactement ce que dit la référence. Il montre comment forwardRef est utilisé avec les composants DOM:

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

ref contient une référence à un élément DOM.

Il est possible d'utiliser forwardRef avec des composants de classe de la même manière:

const FancyButton = React.forwardRef((props, ref) => (
  <SomeClassComponent ref={ref} />
));

ref contient une référence à une instance de classe.

0
estus