📍Presentational vs Container
구분 | Presentational | Container |
쓰임새 | 데이터가 유저에게 어떻게 보여질지에 대해서만 다루는 컴포넌트 | 어떤 데이터가 유저에게 보여질지 결정하는 컴포넌트 |
역할 | View | 비즈니스 로직 |
예시 | 강아지 사진 리스트를 렌더링하는 컴포넌트 | 강아지 사진들을 fetch하는 컴포넌트 |
📍Presentational Components
- 예시
import React from "react";
export default function DogImages({ dogs }) {
return dogs.map((dog, i) => <img src={dog} key={i} alt="Dog" />);
}
- props로 데이터를 받는다
- 이 컴포넌트의 주요 기능은 단순히 받은 데이터를 렌더링하는 것
- 따라서 스타일 시트를 포함하며 데이터는 건드리지 않음
- UI를 위한 데이터인 props 이외의 상태를 갖지 않는다
⭐Container 컴포넌트로부터 데이터를 받는다
📍Container Components
- 예시
import React from "react";
import DogImages from "./DogImages";
export default class DogImagesContainer extends React.Component {
constructor() {
super();
this.state = {
dogs: []
};
}
componentDidMount() {
fetch("https://dog.ceo/api/breed/labrador/images/random/6")
.then(res => res.json())
.then(({ message }) => this.setState({ dogs: message }));
}
render() {
return <DogImages dogs={this.state.dogs} />;
}
}
- presentational 컴포넌트에 데이터를 전달하는 것이 주요 기능
- 스타일 시트를 포함하지 않음
- 이 2가지 컴포넌트를 조합하여 비즈니스 로직과 뷰를 분리
📍Hooks
Container/Presentational 패턴은 대부분 React Hooks로 대체될 수 있다
- Hooks의 도입으로 conatiner 컴포넌트 없이 stateful 컴포넌트를 만들기 쉬워졌다
- 예시
export default function useDogImages() {
const [dogs, setDogs] = useState([]);
useEffect(() => {
fetch("https://dog.ceo/api/breed/labrador/images/random/6")
.then(res => res.json())
.then(({ message }) => setDogs(message));
}, []);
return dogs;
}
- 위의 훅을 사용하여 따로 container 컴포넌트를 만들지 않고 Hook를 받아와 presentation 컴포넌트를 직접 사용할 수 있다
import React from "react";
import useDogImages from "./useDogImages";
export default function DogImages() {
const dogs = useDogImages();
return dogs.map((dog, i) => <img src={dog} key={i} alt="Dog" />);
}
- useDogImages 훅을 사용하여 비즈니스 로직과 뷰를 분리
📍장점
- 자연스럽게 관심사의 분리 구현
presentational 컴포넌트 : UI를 담당하는 순수 함수
container 컴포넌트 : 데이터(상태)를 담당
- presentational 컴포넌트를 재사용 가능 (데이터 변경이 없으므로)
- props로 데이터만 넘겨주면 되므로 테스트가 쉬움
📍단점
- Hooks로 대체 가능하여 패턴을 사용할 이유가 없어짐
- 현재는 클래스형 컴포넌트를 사용하지 않아도 됨
📍참고
https://www.patterns.dev/posts/presentational-container-pattern/