Netflix 클론 만들다가 발견한 디자인 패턴을 소개하려고 한다. 바로 Compound Components 패턴이다.
Card안에 관련 컴포넌트가 자식으로 여러가지 들어간다고 해보자.
// App.js
return (
<Card classes="mr" key={id}>
<CardBody>
<CardImage src={image} alt={title} />
<CardTitle>{title}</CardTitle>
<CardText>{desc}</CardText>
<CardButton>{ctaText}</CardButton>
</CardBody>
</Card>
);
그럼 자식들을 일단 다른 폴더에 만들어야 하고 import도 다 따로 해야한다. 그러나 이 모든것을 Card 컴포넌트에 모아서 쓰는 패턴이 있다.
바로 Compound Component 패턴이다.
그럼 Card 컴포넌트로 일단 가보자.
// Card.js
import {
Container,
Body,
Title,
Text,
Image,
Button,
} from './style/Card.style';
function Card({ children, ...restProps }) {
return <Container {...restProps}>{children}</Container>;
}
Card.Body = function CardBody({ children, ...restProps }) {
return <Body {...restProps}>{children}</Body>;
};
Card.Title = function CardTitle({ children, ...restProps }) {
return <Title {...restProps}>{children}</Title>;
};
Card.Text = function CardText({ children, ...restProps }) {
return <Text {...restProps}>{children}</Text>;
};
Card.Image = function CardImage({ src, alt, ...restProps }) {
return <Image src={src} alt={alt} {...restProps} />;
};
Card.Button = function CardButton({ children, ...restProps }) {
return <Button {...restProps}>{children}</Button>;
};
export default Card;
우선 Card.style.js 에서 styled-components로 스타일된 컴포넌트를 만들어야 한다. 그 과정은 이미 뻔하니깐 생략하겠다.
그리고 Card.js로 와서 Card 컴포넌트를 만들고 .(dot notation)
으로 Card 객체(jsx 오브젝트) 안에 static하게 prop을 추가한다. 그리고 function을 통해 리턴해주면 된다.
그리고 Card/index.js로 돌아와서 선언하자
import Card from './Card';
export { Card };
그리고 다시 App에 와서 사용해보자
// App.js
import { Card } from './components/card';
return (
<Card classes="mr" key={id}>
<Card.Body>
<Card.Image src={image} alt={title} />
<Card.Title>{title}</Card.Title>
<Card.Text>{desc}</Card.Text>
<Card.Button>{ctaText}</Card.Button>
</Card.Body>
</Card>
);
참고로 import할때 card폴더안에서 어떤 파일을 명시하지 않았을 경우 자동으로 index.js를 가리키게 되므로 참고바람!
요렇게 compound component 패턴을 사용하면, Card의 자식으로 들어갈 컴포넌트를 일일이 다 따로 만들지 않아도 되고, 가독성도 올라간다.