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.
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.
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.
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
.
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
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
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>;
Où 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} />
));
Où ref
contient une référence à une instance de classe.