Container는 Redux를 리액트에 연동했을 때 사용하는 개념이다.
(Redux에는 Container라는 개념이 없음)
여기서 Container는 Container Component의 줄임말이며, 컴포넌트는 리액트 컴포넌트를 의미한다.
결국, Container는 Redux의 일부 state와 dispatch를 포함하는 리액트 컴포넌트이다.
Container의 정의를 그림으로 나타내면 다음과 같다.
즉, 요약하면 Component는 Redux에 대해서 모르는 일반적인 리액트 컴포넌트를 의미하고,
Container는 Redux와 연결된 리액트 컴포넌트를 의미한다.
Container를 만들기 위해서는 리액트 컴포넌트와 Redux를 연결해야 하는데, 이때 react-redux
라는 라이브러리를 사용할 수 있다.
Redux에는 다양한 Binding Library(Redux와 React를 연동)들이 있는데,
그 중 하나가 바로 react-redux
이다.
Provider의 하위 컴포넌트들이 리덕스 Store에 접근할 수 있게 해준다.
리액트의 Context API 처럼, 최상위 컴포넌트인 App
컴포넌트를 Provider로 감싸준다.
value
를 prop
으로 가지는 반면, react-redux의 Provider는 store
를 prop
으로 가진다. (여기서 store는 Redux Store를 의미함)import { Provider } from 'react-redux';
import createStore from './createReduxStore';
const store = createStore();
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
function mapStateToProps(state, ownProps?)
// state: 전체 state에서 연결할 컴포넌트에 필요한 state만 추출해서 mapping
// ownProps(옵션): mapping시킬 타겟 컴포넌트가 가지고 있는 자체 prop
function mapStateToProps(state) {
const { posts, comments } = state;
return {
post: posts,
comments: comments;
}
}
// ownProps에 들어있는 postId 값을 사용해서 posts에서 해당되는 아이디 값을 가진 post를 찾아 해당 post만을 리턴
function mapStateToProps(state, ownProps) {
const { posts, comments } = state;
const targetPost = posts.find((post) => {
return post.id === ownProps.postId;
});
return {
post: targetPost,
}
}
아래 코드를 보면, Action(카운트 증가 및 감소)을 Dispatch하기 위한 함수를 만들고, 이 함수를 객체 형태로 만들어서 리턴한다.
function mapDispatchToProps (dispatch) {
return {
increaseCount: () => {
dispatch({ type: 'INCREMENT_COUNT' });
},
decreaseCount: () => {
dispatch({ type: 'DECREASE_COUNT' });
},
}
}
function mapDispatchToProps (dispatch, ownPoprs) {
return {
increaseCount: () => {
dispatch({
type: 'INCREMENT_COUNT',
counterId: ownProps.counterId,
});
},
decreaseCount: () => {
dispatch({
type: 'DECREASE_COUNT',
counterId: ownProps.counterId,
});
},
}
}
function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)
// mergeProps: 연결하는 컴포넌트에 최종적으로 전달될 props를 결정하는 함수
// options: 추가적인 옵션들을 사용하기 위한 객체
connect() 함수 예시
Step 1 :
mapStateToProps()
함수와 mapDispatchToProps()
함수를 만들고,
connect()
함수의 파라미터로 넣어서 호출한다. 이렇게 호출하면 Wrapper Function이 리턴되는데,
이 Wrapper Function을 사용하면 어떤 리액트 컴포넌트든지 Container로 만들 수 있다.
Step 2 :
Wrapper Function을 통해 Redux와 Counter 컴포넌트를 연결하면 Container Component가 리턴된다.
import Counter from '../components/Counter';
function mapStateToProps(state) {
return {
count: state.count,
}
}
function mapDispatchToProps (dispatch) {
return {
increaseCount: () => {
dispatch({ type: 'INCREASE_COUNT' });
},
decreaseCount: () => {
dispatch({ type: 'DECREASE_COUNT' });
},
}
}
// Step 1: 리액트 컴포넌트를 파라미터로 넣어서 호출하면 Redux에 연결시킬 수 있는 Wrapper Function을 리턴
const connectCount = connect(mapStateToProps, mapDispatchToProps);
// Step 2: Redux와 연결된 Container 컴포넌트를 리턴
const CounterContainer = connectCount(Counter);
// Step 1, 2를 동시에 처리하는 방식
const CounterContainer = connect(mapStateToProps, mapDispatchToProps)(Counter);
export default CounterContainer;
Container : Redux와 연결되어 있는 React 컴포넌트
react-redux
redux와 React를 연동해서 사용할 수 있게 해주는 공식 Binding Library
주요 API
Provider
: 하위 컴포넌트들이 Redux Store에 접근할 수 있게 해주는 상위 컴포넌트mapStateToProps()
: Redux State를 타겟 React 컴포넌트의 props로 연결시켜주는 함수mapDispatchToProps()
: Redux dispatch를 타겟 React 컴포넌트의 props로 연결connect()
: Redux와 React 컴포넌트를 연결시켜주는 역할을 하는 함수 Redux와 React 연동 과정