클래스 기반 컴포넌트에서 React.forwardRef를 사용하는 방법은 무엇입니까?


112

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를 사용합니다.

답변:


108

에 대해 항상 동일한 prop을 사용한다는 아이디어 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를 전달하기 위해 다른 prop을 가져야하지만 허브 아래에서 할 수 있습니다. 대중이 일반 심판으로 사용하는 것이 중요합니다.


4
React-Redux connect또는 marterial-ui 와 같은 HOC로 구성 요소를 래핑하면 어떻게 withStyles합니까?
J. Hesters 2018

connect또는 의 문제는 무엇입니까 withStyles? 모든 HOC를 감싸고 forwardRef내부적으로 "safe"prop을 사용하여 참조를 체인의 가장 낮은 구성 요소에 전달해야합니다.
Mr Br

setState를 사용할 때 Enzyme에서 ​​이것을 테스트하는 방법에 대한 통찰력이 있습니까?
zero_cool

더 자세한 정보가 필요해서 죄송합니다. 문제가 정확히 무엇인지 확실하지 않습니다.
Mr Br

2
나는 얻는다 : 불변 위반 : 객체는 React 자식으로 유효하지 않습니다 (발견됨 : {$$ typeof, render} 키가있는 객체). 자식 컬렉션을 렌더링하려는 경우 대신 배열을 사용하십시오.
Brian Loughnane

9
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()} />
)

ref를 클래스로 전달하려면 다른 prop 이름을 사용해야합니다. innerRef많은 라이브러리에서 일반적으로 사용됩니다.


당신의 코드에 beautifulInputElement오히려이 요소 반응보다 더 많은 기능은, 그것은 다음과 같이해야한다const beautifulInputElement = <BeautifulInputForwardingRef ref={ref => ref && ref.focus()} />
올리비에 Boissé

8

기본적으로 이것은 단지 HOC 함수입니다. 클래스와 함께 사용하고 싶다면 혼자서 할 수 있고 일반 소품을 사용할 수 있습니다.

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

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

이 패턴은 예를 들어에서 사용되며 거기 styled-components에서 호출 innerRef됩니다.


3
다른 이름의 소품을 사용 innerRef하면 요점이 완전히 누락됩니다. 목표는 완전한 투명성입니다. <FancyButton>a가 일반 DOM 요소 인 것처럼 처리 할 수 ​​있어야 하지만 스타일 구성 요소 접근 방식을 사용하면이 구성 요소가 .NET 대신 refs에 대해 임의로 이름이 지정된 prop을 사용한다는 사실을 기억해야합니다 ref.
user128216

2
어쨌든 스타일 구성 요소는를 사용하여 자식에게 ref를 전달 하기 위해 지원innerRef중단React.forwardRef 하려고합니다. 이는 OP가 수행하려고하는 것입니다.
user128216

5

다음과 같은 경우 고차 구성 요소로 수행 할 수 있습니다.

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


3

여러 다른 구성 요소에서이를 재사용해야하는 경우이 기능을 다음과 같이 내보낼 수 있습니다. 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.