如何在基于类的组件中使用React.forwardRef?

时间:2018-07-25 19:37:12

标签: javascript reactjs

我正在尝试使用React.forwardRef,但是在如何使它在基于类的组件(不是HOC)中工作的问题上遇到了麻烦。

文档示例使用元素和功能组件,甚至将类包装在函数中以用于更高阶的组件。

因此,从ref.js文件中的类似this的地方开始

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组件。您也可以将引用转发到类组件实例。

来自note in this section.

但是随后他们继续使用HOC,而不仅仅是类。

5 个答案:

答案 0 :(得分:40)

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

所以,基本上,是的,我们被迫使用其他道具来转发ref,但这可以在集线器下完成。公众将其用作常规参考非常重要。

答案 1 :(得分:7)

基本上,这只是一个HOC函数。如果您想在课堂上使用它,可以自己做,并使用常规道具。

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

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

此模式例如在styled-components中使用,在此称为innerRef

答案 2 :(得分: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()} />
)

您需要使用其他prop名称将引用转发到类。 innerRef通常在许多库中使用。

答案 3 :(得分:2)

如果需要在许多不同的组件中重复使用此功能,则可以将此功能导出到类似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

答案 4 :(得分:2)

如果愿意,可以使用更高阶的组件来实现:

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

然后在您的组件文件中:

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) https://www.npmjs.com/package/react-with-forwarded-ref