programing

ref = 'string'이 "레거시"인 이유는 무엇입니까?

yoursource 2021. 1. 15. 19:51
반응형

ref = 'string'이 "레거시"인 이유는 무엇입니까?


React 문서에서 그들은 말합니다 :

React는 또한 모든 컴포넌트의 ref prop으로 문자열 (콜백 대신)을 사용하는 것을 지원하지만, 이 접근 방식은 이 시점에서 대부분 레거시 입니다.

https://facebook.github.io/react/docs/more-about-refs.html

다음 예를 살펴보십시오.

class Foo extends Component {
  render() {
    return <input onClick={() => this.action()} ref={input => (this._input = input)} />;
  }
  action() {
    console.log(this._input.value);
  }
}

다음 대신 이것을 선호해야하는 이유 :

class Foo extends Component {
  render() {
    return <input onClick={() => this.action()} ref='input' />;
  }
  action() {
    console.log(this.refs.input.value);
  }
}

?

두 번째 예가 훨씬 더 깨끗하고 쉬워 보입니다.
문자열 메서드가 더 이상 사용되지 않을 위험이 있습니까?


NB : 나는 문서에있는 진술에 대한 "공식적인"답변을 찾고 있습니다. 개인적 선호도 등에 대해 묻지 않습니다.


아마도 더 간단 할 수도 있지만, 콜백에서 사용될 때와 같은 일부 엣지 케이스에서는 이전 refs API가 어려울 수 있습니다. 모든 종류의 정적 분석도 문자열에 대한 고통입니다. 콜백 기반의 API는 문자열 API가 할 수있는 모든 것을 할 수있는 조금 추가 상세으로합니다.

class Repeat extends React.Component {
  render() {
    return <ul> {
      [...Array(+this.props.times)].map((_, i) => {
        return <li key={i}> { this.props.template(i)    } </li>
      })
    } </ul>
  }
}

class Hello extends React.Component {
  constructor() {
    super();
    this.refDict = {};
  }

  render() {
    return <Repeat times="3" template={i => <span ref= {el => this.refDict[i] = el}> Hello {i} </span>} />
           {/*                                    ^^^ Try doing this with the string API          */}
  }
}

추가 논의와 문자열 기반 api의 가능한 문제에 대한 좀 더 포괄적 인 목록은 콜백 기반 API가 도입 문제 # 1373 에서 찾을 수 있습니다 . 여기에 문제 설명의 목록을 포함하겠습니다.

ref API는 여러 측면에서 깨졌습니다.

  • 클로저 컴파일러 고급 모드와 호환 되려면 this.refs [ 'myname']을 문자열로 참조해야합니다.

  • 단일 인스턴스의 여러 소유자라는 개념을 허용하지 않습니다.

  • 마법의 동적 문자열은 잠재적으로 VM의 최적화를 중단합니다.

  • It needs to be always consistent, because it's synchronously resolved. This means that asynchronous batching of rendering introduces potential bugs.

  • We currently have a hook to get sibling refs so that you can have one component refer to it's sibling as a context reference. This only works one level. This breaks the ability to wrap one of those in an encapsulation.

  • It can't be statically typed. You have to cast it at any use in languages like TypeScript.

  • There's no way to attach the ref to the correct "owner" in a callback invoked by a child. <Child renderer={index => <div ref="test">{index}</div>} /> -- this ref will be attached where the callback is issued, not in the current owner.


The docs call the old string API "legacy" to make it clearer that the callback-based API is the preferred approach, as is discussed in this commit and in this PR which are the ones that actually put those statements to the documentation in the first place. Also note that a few of the comments imply that the string based refs api might be deprecated at some point.


Originally posted by danabramov on https://news.ycombinator.com/edit?id=12093234

  1. String refs are not composable. A wrapping component can’t “snoop” on a ref to a child if it already has an existing string ref. On the other hand, callback refs don’t have a single owner, so you can always compose them.
  2. String refs don’t work with static analysis like Flow. Flow can’t guess the magic that framework does to make the string ref “appear” on this.refs, as well as its type (which could be different). Callback refs are friendlier to static analysis.
  3. The owner for a string ref is determined by the currently executing component. This means that with a common “render callback” pattern (e.g. <DataTable renderRow={this.renderRow} />), the wrong component will own the ref (it will end up on DataTable instead of your component defining renderRow).
  4. String refs force React to keep track of currently executing component. This is problematic because it makes react module stateful, and thus causes weird errors when react module is duplicated in the bundle.

ReferenceURL : https://stackoverflow.com/questions/37468913/why-ref-string-is-legacy

반응형