본문 바로가기
Language/React

[React 공식 Advanced Doc] Fragment

by ocwokocw 2021. 2. 11.

- 이 글은 React 공식 홈페이지 Docs v16.8.3 (https://reactjs.org/docs) 에 기반하여 작성한 글입니다.

- Fragments

React 에서 1 Component 안에서 복수개의 element들을 반환하는 형태가 일반적이다. 이때 반환하는 element 부분에서 최상위 노드가 1개 여야 하는데, "Fragment"는 여러개의 element 노드를 강제로 <div>같은 DOM 노드로 엮을 필요 없이 1개의 그룹으로 엮어준다.

 

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}

 

React.Fragment를 선언할 때 줄임문법(일종의 sugar syntax)가 있긴 하지만, 공식 Doc 에서는 일반적인 tool 모두가 지원하지는 않는다고 하는거 보니 쓰기를 권장하지는 않는 것 같다.


- Motivation

앞에서 일반적으로 Component 에서 복수개의 element들을 반환한다고 했다. 아래 예제를 한번보자.

 

class Table extends React.Component {
  render() {
    return (
      <table>
        <tr>
          <Columns />
        </tr>
      </table>
    );
  }
}

 

<Columns />는 HTML에서 <table>을 구성하기 위해 여러개의 <td> element 들을 반환할 것이다. React 에서는 component를 rendering할 때 최상위 노드는 1개 여야 하므로 아래와 같은 형태로 오류가 나지 않게 만들어야 되는데, 하지만 이렇게 되면 HTML의 <table>이 유효하지 않게 된다.

 

class Columns extends React.Component {
  render() {
    return (
      <div>
        <td>Hello</td>
        <td>World</td>
      </div>
    );
  }
}

 

최상위 노드는 정말 1개 여야 할까? <div>를 없애고 <td>2개를 반환하려고 시도해보자.

1개의 root 노드만 반환하라고 에러를 뱉는다. <Table />의 결과는 아래와 같다.

 

<table>
  <tr>
    <div>
      <td>Hello</td>
      <td>World</td>
    </div>
  </tr>
</table>

 

사실 React DOC 에서는 결과값이 위와 같다고 하지만 실제로 해보면 위와같은 결과는 나오지 않는다. 친절하게 에러를 뱉는다.

분명 최상위의 노드는 하나여야 하는데 <td>상위에는 붙일 노드가 마땅치 않다 이를 어떻게 해결해야 할까? "Fragment"를 쓰면 해결할 수 있다.


-Usage

class Columns extends React.Component {
  render() {
    return (
      <React.Fragment>
        <td>Hello</td>
        <td>World</td>
      </React.Fragment>
    );
  }
}

 

위의 Component가 rendering 되면 아래와 같이 올바른 <Table /> 결과값이 된다.

 

<table>
  <tr>
    <td>Hello</td>
    <td>World</td>
  </tr>
</table>


-Short Syntax

fragments를 선언할 수 있는 간단한 문법이 있다. 마치 비어있는 tag처럼 선언하면 된다.

 

class Columns extends React.Component {
  render() {
    return (
      <>
        <td>Hello</td>
        <td>World</td>
      </>
    );
  }
}

 

<></> 태그는 여태까지 써왔던 element처럼 사용하면 되긴하지만 key나 attribute를 지원하지 않는다.그리고 주의할 점이 하나 있다. 많은 tool 들은 아직 이 문법을 지원하지 않는다. 많은 tool들이 지원하게 될때까지는 <React.Fragment> 태그를 명시적으로 쓰길 권장한다.


- Keyed Fragments

<></>문법이 아닌 <React.Fragment>와 같이 명시적으로 fragment를 선언했다면 아마 key를 같이 쓰게 될 것이다.

collection을 fragment의 배열로 맵핑시키는 예제를 통해서 무슨말인지 이해해보자.

 

function Glossary(props) {
  return (
    <dl>
      {props.items.map(item => (
        // Without the `key`, React will fire a key warning
        <React.Fragment key={item.id}>
          <dt>{item.term}</dt>
          <dd>{item.description}</dd>
        </React.Fragment>
      ))}
    </dl>
  );
}

 

위의 코드에서 key를 사용하지 않으면 React에서 warning을 뱉을 것이다. 현재는 React.Fragment에 attribute중 key만 사용할 수 있다. 공식 Doc 에서는 event handler와 같은 추가적인 attribute를 추가할 계획이 있다고 한다.

댓글