-
[React] cloneElementFront-End(Web)/React - 프레임워크(React, Next) 2023. 3. 22. 03:15반응형
React로 개발하면서, 공통 UI 혹은 기능을 가진 랩핑 컴포넌트를 만드는 경우가 종종 있다.
type Props = ButtonHTMLAttributes<HTMLButtonElement>; function AddTravelerButton({ children, ...props }: PropsWithChildren<Props>): JSX.Element { return ( <Button {...props}> <Text>{children}</Text> </Button> ); }
이 랩핑 컴포넌트에서 Props로 받은 값으로 특정 속성을 만든다고 가정하자.
해당 컴포넌트에서 이 속성값을 사용하는 건 쉽지만, 내부의 {children} 에 이 속성값을 전달할 방법이 전혀 떠오르지 않았다.
이를 구현하기 위해 리서치해본 결과, cloneElement라는 React의 기능을 활용하면 되었다.
💙 cloneElement
const clonedElement = cloneElement(element, props, ...children)
React에서 엘리먼트를 조작하기 위해 제공되는 API 중 하나이다.
특정 엘리먼트에 새로운 설정을 추가한 새 엘리먼트를 복제 및 반환을 해준다. 인자는 아래 3개를 받는다.
- element : 복제할 원본 엘리먼트
- props : 원본 엘리먼트에 추가할 props(객체 형태로 전달). 기존 props에 추가된 값들을 오버라이딩한다.
- [...children] : 복제된 객체의 children
cloneElement를 통해 같은 베이스의 일부 기능만 다른 코드들이 양산되는 것을 지양하고, 효율적으로 이를 확장할 수 있다.
공식문서도, children 엘리먼트의 props 추가/수정을 통한 컴포넌트 기능 확장이 가능하다고 언급한다.
- 샘플코드
const Parent = ({ children, one }) => { const two = one + 1; return <>{React.cloneElement(children, { two: two })}</>; }; const Child = ({ two }) => <div>one + one = {two}</div>; const App = () => ( <Parent one={1}> <Child /> </Parent> );
부모 컴포넌트는 cloneElement를 반환하면 된다. 첫 번째 인자로 children, 두 번째 인자로 추가할 props를 제공한다.
자식 컴포넌트는 별도의 전달 없이도, cloneElement를 통해 전달한 props들을 받을 수 있다.
이처럼, 부모 컴포넌트에서 생성 혹은 계산된 값을 자식 컴포넌트(children)에게도 전달하기 위해 많이 사용된다.
- Pitfall(잠재위험)?
공식문서에서 볼 수 있듯, cloneElement를 레거시이자 pitfall한 기능으로 안내하고 있다.(props 추가/수정 트래킹이 힘듬)
그 대안으로, render props 패턴을 권장하고 있다.
const Parent = ({ render }) => { const newProp = 'some new prop'; return render(newProp); } const Child = ({ newProp }) => <div>{newProp}</div>; const App = () => ( <Parent render={props => <Child newProp={props} />} /> );
이 형태로도 충분히 구현은 가능하며, 단 차이점은 cloneElement는 기존 자식 컴포넌트의 key, ref를 유지해준다는 것이다.
위를 착안해서, 상황에 맞게 적절한 패턴을 사용하면 될 것 같다!
📎 출처
- [cloneElement] React 공식문서(신) : https://react.dev/reference/react/cloneElement
- [cloneElement 사용예시] heyoki! 님의 블로그 : https://itchallenger.tistory.com/711
- [cloneElement 사용예시] 수박수 님의 블로그 : https://watermelonlike.tistory.com/entry/React-Clone-element
반응형'Front-End(Web) > React - 프레임워크(React, Next)' 카테고리의 다른 글
[Next.js] Next.js 13 변경사항 (0) 2023.01.14 [React] Concurrency(동시성) - #4. Transition API (0) 2022.11.03 [React] Concurrency(동시성) - #3. Concurrent Rendering (0) 2022.10.27 [React] Concurrecy(동시성) - #2. Error Boundary (0) 2022.10.27 [React] Concurrency(동시성) - #1. Suspense와 React.lazy (0) 2022.10.24