Как использовать React.forwardRef в компоненте на основе класса?
Я пытаюсь использовать React.forwardRef, но размышляю над тем, как заставить его работать в компоненте на основе классов (не HOC).
В примерах документов используются элементы и функциональные компоненты, в том числе классы в функциях для компонентов более высокого порядка.
Итак, начиная с чего-то вроде этого в файле ref.js
:
const TextInput = React.forwardRef(
(props, ref) => (<input type="text" placeholder="Hello World" ref={ref} />)
);
и вместо этого определяя это как что-то вроде этого:
class TextInput extends React.Component {
render() {
let { props, ref } = React.forwardRef((props, ref) => ({ props, ref }));
return <input type="text" placeholder="Hello World" ref={ref} />;
}
}
или же
class TextInput extends React.Component {
render() {
return (
React.forwardRef((props, ref) => (<input type="text" placeholder="Hello World" ref={ref} />))
);
}
}
только работает:/
Кроме того, я знаю, я знаю, реф не способ реакции. Я пытаюсь использовать стороннюю библиотеку холстов и хотел бы добавить некоторые из их инструментов в отдельные компоненты, поэтому мне нужны прослушиватели событий, поэтому мне нужны методы жизненного цикла. Это может пойти другим путем позже, но я хочу попробовать это.
Документы говорят, что это возможно!
Пересылка ссылок не ограничивается компонентами DOM. Вы также можете пересылать ссылки на экземпляры компонентов класса.
из примечания в этом разделе.
Но затем они продолжают использовать HOC вместо просто классов.
Ответы
Ответ 1
Идея всегда использовать одну и ту же опору для ref
может быть достигнута путем прокси экспорта класса с помощью помощника.
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}
/>);
Итак, в основном, да, мы вынуждены иметь другую опору для пересылки реф, но это можно сделать под хабом. Важно, чтобы публика использовала его как нормальный реф.
Ответ 2
В принципе, это просто функция HOC. Если вы хотите использовать его с классом, вы можете сделать это самостоятельно и использовать обычные реквизиты.
class TextInput extends React.Component {
render() {
<input ref={this.props.forwardRef} />
}
}
const ref = React.createRef();
<TextInput forwardRef={ref} />
Этот шаблон используется, например, в styled-components
и он называется innerRef
.
Ответ 3
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()} />
)
Вам нужно использовать другое имя для пересылки ссылки в класс. innerRef
обычно используется во многих библиотеках.
Ответ 4
Это может быть выполнено с помощью компонента более высокого порядка, если вам нравится:
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
А затем в вашем файле компонента:
class Boop extends React.Component {
render() {
const { forwardedRef } = this.props
return (
<div ref={forwardedRef} />
)
}
}
export default withForwardedRef(Boop)
Я выполнил предварительную работу с тестами и опубликовал пакет для этого, react-with-forwarded-ref
: https://www.npmjs.com/package/react-with-forwarded-ref
Ответ 5
В том случае, если вам нужно использовать это во многих компонентах различий, вы можете экспортировать эту способность во что-то вроде withForwardingRef
const withForwardingRef = <Props extends {[_: string]: any}>(BaseComponent: React.ReactType<Props>) =>
React.forwardRef((props, ref) => <BaseComponent {...props} forwardedRef={ref} />);
export default withForwardingRef;
использование:
const Comp = ({forwardedRef}) => (
<input ref={forwardedRef} />
)
const EnhanceComponent = withForwardingRef<Props>(Comp); // Now Comp has a prop called forwardedRef
Ответ 6
Это именно то, что говорится в ссылке. Он показывает, как forwardRef
используется с компонентами 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
содержит ссылку на элемент DOM.
Можно использовать forwardRef
с компонентами класса так же:
const FancyButton = React.forwardRef((props, ref) => (
<SomeClassComponent ref={ref} />
));
Где ref
содержит ссылку на экземпляр класса.