목차

     

     

    지정한 Element를 복사해 반환한다.

    부모에서의 props를 자식에게 props를 전달해야하는 경우 사용할 수 있다.

    ✏️ 사용하려고한 이유

    1. 부모 컴포넌트 안에 있는 자식 컴포넌트를 외부에서도 볼 수 있게 하기 위해서
    2. Props 드릴링을 피하기 위해서
    3. Page > (Container or Manager) > (Component or SearchForm) 구조를 사용하기 위해서

    📌 자주 사용한 컴포넌트 구조

    const App = () => {
      return (
        <Page>
          <Manager>
            <SearchForm />
          </Manager>
    
          <Container>
            <Component />
          </Container>
        </Page>
      )
    }
    • Page Component: 모든 API Request를 요청하는 역할을 한다.
    • Manager Component : children component에게 Action 함수를 전달하거나 데이터를 가공하여 전달한다. ( 하위 컴포넌트로 SearchForm이 올 경우 사용한다. )
      • 처리해야할 Action 함수가 없거나 간단하다면 사용하지 않았다.
    • Container Component: children component에게 Action 함수를 전달하거나 데이터를 가공하여 전달한다. ( 하위 컴포넌트로 Table이 올 경우 사용한다. )
      • 처리해야할 Action 함수가 없거나 간단하다면 사용하지 않았다.
    • Component: UI를 담당한다.
    • SearchForm Component: 검색 폼이나 폼을 사용하는 UI를 담당한다.

    ✏️ 사용법

    Page

    props 드릴링을 안하고 Child에게 바로 전달 할 수 있고, 외부에서도 볼 수 있다.

    /**
     * @page
     */
    const Page = () => {
      const apiResponse = 'apiResponse'
    
      return (
        <Parent>
          <Child response={apiResponse} />
        </Parent>
      )
    }

    Parent

    import React, { cloneElement, Fragment, JSXElementConstructor, ReactElement } from 'react'
    
    interface ParentProps {
      children: ReactElement<{ data: string; count: number }, string | JSXElementConstructor<any>>
    }
    
    /**
     * @container
     */
    const Parent = ({ children }: ParentProps) => {
      return <Fragment>{cloneElement(children, { data: 'data', count: 1 })}</Fragment>
    }

    Child

    중요포인트: 전달받는 props에 undefined도 올 수 있음을 정의해야한다.

    interface ChildProps {
      data?: string
      count?: number
      response: string
    }
    
    /**
     * @component
     */
    const Child = ({ data, count, response }: ChildProps) => {
      return (
        <Box>
          {data}
          <Box>{count}</Box>
          <Box>{response}</Box>
        </Box>
      )
    }

    ✏️ 주의사항 두 가지

    1. 전달받는 props에 undefined도 올 수 있음을 정의해야한다.
    Child Component가 단독으로 쓰이면, props를 받을 것이 없기 때문이다.

    // Props를 전달 받을 수도 있음!!
    <Parent>
      <Child />
    </Parent>
    // Props를 전달 받을 수가 없음!!
    <Child />

    2. props로 undefined를 전달 받을 수 없다면 사용할 수 없다.
    따라서 전달 받는 컴포넌트의 해당 props에 옵셔널 체이닝 연산자를 사용해야한다.

    만약 2번을 회피하려면 다른 방법을 사용할 수 있다. 단 의도에 맞게 사용해야한다.

     

    ✏️ 다른 방법

    page

    /**
     * @page
     */
    const Page = () => {
      const apiResponse = 'apiResponse'
    
      return <Parent>{(props) => <Child response={apiResponse} {...props} />}</Parent>
    }

    Parent

    import { ReactNode } from 'react'
    
    interface ParentProps {
      children: (props: { data: string; count: number }) => ReactNode
    }
    
    /**
     * @container
     */
    const Parent = ({ children }: ParentProps) => {
      return <Fragment>{children({ data: 'data', count: 1 })}</Fragment>
    }

    Child

    interface ChildProps {
      data: string
      count: number
      response: string
    }
    
    /**
     * @component
     */
    const Child = ({ data, count, response }: ChildProps) => {
      return (
        <Box>
          {data}
          <Box>{count}</Box>
          <Box>{response}</Box>
        </Box>
      )
    }

    ✏️ 두 방법의 공통점

    부모에서의 props를 children에게 props를 전달해야하는 경우 사용할 수 있다.

    ✏️ 두 방법의 차이점

    두 번째 방법은 props를 수정하거나 변경할 수 없다. 즉 복제하지 않는다.

    첫 번째 방법은 props를 수정하거나 변경할 수 있다. 즉 얕은 복제를 한다.

     

    + Recent posts