React.cloneElement와 this.props.children을 언제 사용해야합니까?


118

나는 여전히 React에서 멍청한 사람이고 인터넷의 많은 예제에서 혼란스러워하는 자식 요소를 렌더링하는이 변형을 봅니다. 일반적으로 나는 이것을 본다 :

class Users extends React.Component {
  render() {
    return (
      <div>
        <h2>Users</h2>
        {this.props.children}
      </div>
    )
  }
}

그러나 다음과 같은 예가 있습니다.

<ReactCSSTransitionGroup
     component="div"
     transitionName="example"
     transitionEnterTimeout={500}
     transitionLeaveTimeout={500}
     >
     {React.cloneElement(this.props.children, {
       key: this.props.location.pathname
      })}
</ReactCSSTransitionGroup>

이제 나는 api를 이해하지만 문서 는 내가 그것을 사용해야 할 때를 정확하게 밝히지 않습니다.

그래서 하나는 다른 하나는 할 수없는 무엇을합니까? 누군가가 더 나은 예를 들어 설명해 줄 수 있습니까?


3
youtube.com/watch?v=hEGg-3pIHlE 이 사람이 cloneElement를 어떻게 사용하는지 보여주고 있습니다. 몇 가지 예에 대해이 확인
iurii

답변:


69

편집하다:

Vennesa의 대답대신 .

실물:

우선, React.cloneElement 예제는 자식이 단일 React 요소 인 경우에만 작동합니다.

거의 모든 {this.props.children}것이 당신이 원하는 것입니다. 복제는 상위가 요소를 보내고 하위 구성 요소가 해당 요소의 일부 소품을 변경하거나 실제 DOM 요소에 액세스하기 위해 ref와 같은 것을 추가해야하는 일부 고급 시나리오에서 유용합니다.

위의 예에서 자식을 제공하는 부모는 구성 요소에 대한 키 요구 사항을 알지 못하므로 주어진 요소의 복사본을 만들고 개체의 고유 식별자를 기반으로 키를 추가합니다. 키의 기능에 대한 자세한 정보 : https://facebook.github.io/react/docs/multiple-components.html


183

props.children실제 아이들이 아닙니다. 그것은 descriptor아이들의 것입니다. 따라서 실제로 변경할 것이 없습니다. 소품을 변경하거나 기능을 편집 할 수 없습니다. 당신은 read from it. 수정해야하는 경우 다음을 사용 new elements하여 만들어야합니다.React.CloneElement .

https://egghead.io/lessons/react-use-react-cloneelement-to-extend-functionality-of-children-components

예 :

다음과 같은 구성 요소의 주요 렌더링 기능 App.js:

render() {   
    return(
            <Paragraph>
              <Sentence>First</Sentence>
              <Sentence>Second</Sentence>
              <Sentence>Third</Sentence>
            </Paragraph>   
    ) 
}

이제의 onClick각 자식에 를 추가해야한다고 가정 해 보겠습니다 Paragraph. 그래서 Paragraph.js당신은 할 수 있습니다 :

render() {
        return (
          <div>
          {React.Children.map(this.props.children, child => {
            return React.cloneElement(child, {
              onClick: this.props.onClick })   
         })}
         </div>
       ) 
}

그런 다음 간단히 다음을 수행 할 수 있습니다.

render() {   
  return(
        <Paragraph onClick={this.onClick}>
          <Sentence>First</Sentence>
          <Sentence>Second</Sentence>
          <Sentence>Third</Sentence>
        </Paragraph>   
   ) 
}

참고 :React.Children.map 기능 만 볼 수 top level는 그 요소를 렌더링하는 것들 중 하나를 참조하지 않는 요소; 즉, 어린이 (여기서는 <Sentence />요소) 에게 직접 소품을 제공합니다 . 소품을 더 전달해야하는 경우 소품을 사용하려는 요소 <div></div>중 하나가 내부에 있다고 가정 해 보겠습니다 .이 경우를 사용하여 수행 할 수 있습니다 . 확인 공급자와 소비자 등의 요소를.<Sentence />onClickContext APIParagraphSentence


11
이것은 실제 사례에 대한 명확한 대답입니다. 더 많은 찬성표가 필요합니다.
SeaWarrior404

1
@ SeaWarrior404와 동의-그의 사용자 인터페이스가 제목으로 "Users"/ 복수형을 가지고 있기 때문에 OP가 단일 자식이 아닌 컬렉션을 반복하려고 찾고 있다고 생각합니다. 사용 React.Children.map과 함께 React.cloneElement@vennesa가 지적 하듯, 매우 강력
jakeforaker

23

실제로 React.cloneElementthis.props.children.

PropTypes.element부모가 해당 컴포넌트 내부에 대한 지식을 갖지 않고 (예 : 이벤트 핸들러 연결 또는 key/ ref속성 할당 ) props를 추가 / 오버라이드하기 위해 react elements ( ) 를 복제해야 할 때 유용합니다 .

또한 반응 요소는 변경할 수 없습니다 .

React.cloneElement (element, [props], [... children])는 다음과 거의 동일합니다. <element.type {...element.props} {...props}>{children}</element.type>


그러나 childrenReact 의 prop은 특히 포함 ( 구성 ), React.ChildrenAPI와 페어링에 사용되며 React.cloneElement, props.children을 사용하는 구성 요소는 내부적으로 더 많은 로직 (예 : 상태 전환, 이벤트, DOM 측정 등)을 처리하면서 렌더링 부분을 어디에서 사용하든 React Router <switch/>또는 복합 구성 요소 <select/>가 좋은 예입니다.

마지막으로 언급 할 가치가있는 것은 반응 요소가 props.children으로 제한되지 않는다는 것입니다.

function SplitPane(props) {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
  );
}

function App() {
  return (
    <SplitPane
      left={
        <Contacts />
      }
      right={
        <Chat />
      } />
  );
}

그들은 의미가 그 어떤 소품이 될 수, 키, 구성 요소에 대한 좋은 계약을 정의하는 것이었다 그래서 그것의 소비자가 사용하고 여부에 관계없이, 기본 구현 세부 사항에서 분리 될 수 있음을 React.Children, React.cloneElement또는도 React.createContext.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.