์์ ์๋ ํญ์ "container"๋ผ๋ ํด๋์ "component"๋ผ๋ ํด๋๊ฐ ์์ต๋๋ค. ์ด ๋ถ๋ฆฌ์ ๋ํ ์๊ฐ์ ๋ฌด์์ ๋๊น?
"์ปจํ ์ด๋"๋ ์ค๋งํธ ๊ตฌ์ฑ ์์์ ๋๊น ์๋๋ฉด ๋ผ์ฐํ ๊ตฌ์ฑ ์์ ๋๋ ๋ค๋ฅธ ๊ฒ์ ๋๊น? "๊ตฌ์ฑ ์์"์๋์ ๊ตฌ์ฑ ์์๋ ํญ์ ๋ฉ์ฒญํด์ผํฉ๋๊น?
๋๋ฅผ ์ํด container
๋ ๊ฒฝ๋ก์ ํธ๋ค๋ฌ์ด๋ฉฐ ํด๋น ๊ฒฝ๋ก์ ๋ํ redux์ ์ํ๋ ๊ฐ์ ธ์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋ด ์ํ๋ฅผ ์ํ์ผ๋ก ์ ๋ฌํฉ๋๋ค.
์๋ฅผ ๋ค๋ฉด
container / properties.jsx
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actions from 'actions/properties';
import Filter from 'components/properties/filter';
import List from 'components/properties/list';
import Pagination from 'components/properties/pagination';
class PropertiesContainer extends Component {
render() {
return (
<section>
<Filter filter={this.props.properties.params.filter} />
<List items={this.props.properties.items} isFetching={this.props.properties.isFetching} />
<Pagination pagination={this.props.properties.params.pagination} />
</section>
);
}
}
function mapState(state) {
const { properties } = state;
return { properties };
}
function mapDispatch(dispatch) {
return {
actions: bindActionCreators(actions, dispatch),
};
}
const Connector = connect(mapState, mapDispatch)(PropertiesContainer);
export default Connector;
์๋ฅผ ๋ค์ด
components / properties / pagination.jsx
import React, { Component } from 'react';
import Pager from 'components/ui/pager';
class Pagination extends Component {
render() {
const { total, offset, limit } = this.props.pagination;
const current = offset / limit;
return (
<Pager total={total} current={current} />
)
}
}
export default Pagination;
์ ๊ณต ํ ๋งํฌ์์ ์ฝ๊ธฐ :
"A container does data fetching and then renders its corresponding sub-component. "
"์ปจํ ์ด๋"๊ฐ ์ค์ ๋ก redux์์ "์ค๋งํธ ๊ตฌ์ฑ ์์"๋ผ๊ณ ๋ถ๋ฅด๋ ๊ฒ ๊ฐ์ ๋๋์ด ๋ค์์ต๋๋ค. ๊ฒฝ๋ก / ํ์ด์ง๋ ์์ฒด ํด๋๋ฅผ ๊ฐ์ ธ์ผํฉ๋๋ค.
"์ปจํ ์ด๋"์ "๋ผ์ฐํธ ์ฒ๋ฆฌ๊ธฐ"๊ฐ ์ด๋ค ์ ์ผ๋ก๋ ๊ด๋ จ๋์ด์๋ ์ด์ ๋ฅผ ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๊ฒฝ๋ก๋ณ๋ก ์ฑ ๊ตฌ์ฑ ์์๋ฅผ ๊ทธ๋ฃนํํ๋ ๊ฒ์ ๋งค์ฐ ์ผ๋ฐ์ ์ธ ๊ดํ์ ๋๋ค. @theaqua๊ฐ ์ง์ ํ๋ฏ์ด ๊ฐ ๊ฒฝ๋ก ์ฒ๋ฆฌ๊ธฐ / ๊ตฌ์ฑ ์์๋ฅผ ์ค๋งํธ / ์ปจํ ์ด๋ ๊ตฌ์ฑ ์์๋ก ๋ง๋๋ ๊ฒ๋ ์ผ๋ฐ์ ์ ๋๋ค. combineReducers๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋์ผํ ๋ผ์ธ์ ๋ฐ๋ผ ์ํ, ๊ฒฝ๋ก ๋ฐ ์ปจํ ์ด๋๊ฐ ๋ถ๋ฆฌ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ๋ฐ๋ผ์ ๊ทธ๋ค์ ์ข ์ข ํจ๊ป ์ฐ๊ฒฐ๋ฉ๋๋ค.
@ronag ์ปจํ ์ด๋ ์ ํ์ด์ง๋ฅผ ๋ง๋ค ํ์๊ฐ ์๋ค๊ณ ์๊ฐํ์ต๋๋ค. ์ ๋ผ์ฐํธ ํธ๋ค๋ฌ์ redux ์ปค๋ฅํฐ๋ฅผ ํ๊ณณ์ ๋์ ์ ์์ต๋๊น? ๋งค์ฐ ํธ๋ฆฌํฉ๋๋ค. ๋จ์ํ๊ฒ ์ ์งํ์ญ์์ค.
๋ด ์์ฉ ํ๋ก๊ทธ๋จ์๋ 3 ๊ฐ์ ๊ฒฝ๋ก / ํ์ด์ง ๋ง ์์ต๋๋ค. ๋ฐ๋ฉด์ ์ ๋ ๋ง์ ๋
๋ฆฝ์ ์ธ ํจ๋ / ๋ชจ๋์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ํ๋์ ๊ฑฐ๋ํ connect
๋ง๋๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค. ์ ์ด๋ ํจ๋ ์ธก๋ฉด์์ ๋ถํ ํด์ผํฉ๋๋ค.
์ํ์์ ์ํ์ผ๋ก์ ๋ชจ๋ ๋งคํ๊ณผ ๋จ์ผ ํ์ผ์์ ๋ชจ๋ ๋ฐ์ดํฐ ๊ฐ์ ธ ์ค๊ธฐ๋ฅผ ์ํํ๋ฉด ์ ์ง ๊ด๋ฆฌ ํ ์ โโ์์ต๋๋ค. ํนํ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋์ผํ ์์น์์ ๊ฐ์ ธ ์ค๋ ๊ฒฝ์ฐ.
3 ๊ฐ์ ๊ฒฝ๋ก๊ฐ์๋ ๊ฒฝ์ฐ 3 ๊ฐ์ ๊ฒฝ๋ก ์ฒ๋ฆฌ๊ธฐ๊ฐ ํ์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด A.jsx
์์ B.jsx
๋ฐ C.jsx
/containers
.
๊ฐ ์ปจํ
์ด๋์์ redux ์ํ ๋ฐ ์์
๋ฐ์ธ๋ฉ์ ์ผ๋ถ (์ ์ฒด๊ฐ ์๋)๋ฅผ ๊ฐ์ ธ์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ด๊ฒ์ ๋ด ์์ ์ ๊ฐ์ ๊ตฌ์ฑ ์์์ ์ ๋ฌํฉ๋๋ค. ๋ด๊ฐ (๋ด ํ) ์๊ณ ์๊ธฐ ๋๋ฌธ์, ๋งค์ฐ ์ ์ง ๋ณด์์ - ์ฐ๊ฒฐ ๋์ ์ค๋ ํญ์์์ ์ก์
๋ฐ์ธ๋ฉํ๊ธฐ containers
, ๊ทธ๊ฒ์ ๋ ๊ฒ ์ ๋ components
๋ด ์์์์ ๊ฐ์ด ์ข
์ข
๋ฌด ์๊ณ ํ๋ ( ).
๋๋ ๋น์ ์ ์ ์์ ์ดํดํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ด๊ฐ ๋งํ๋ฏ์ด ๋ชจ๋ ๋ฐ์ดํฐ ๊ฐ์ ธ ์ค๊ธฐ๋ฅผ ๊ฑฐ๊ธฐ์ ๋ฃ์ผ๋ฉด ๊ทธ 3 ๊ฐ์ ํ์ผ์ด ๋งค์ฐ ๋ณต์กํด์ง ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ์ ์์ธ์ ๊ธฐ๋ณธ์ ์ผ๋ก "Login, App, Logout"์ด๋ฉฐ App์ ๊ฑฐ์ ๋ชจ๋ ๊ฒ์ ํฌํจํฉ๋๋ค.
๊ฐ ๊ตฌ์ฑ ์์์ ๊ฐ์ ธ์ฌ ๋ฐ์ดํฐ์ ํ์ ๋ฐฉ๋ฒ์ ์ค๋ช
ํ๋ ์ปจํ
์ด๋๊ฐ์๋ Relay
๋๋ฌด ํธํฅ๋์ด์์ ์ ์์ต๋๋ค.
๋๋ ๋น์ ์ ์ ์์ ์๋ํ๊ณ ์ฐ๋ฆฌ๊ฐ ๋๋๋ ๊ณณ์ ๋ณผ ๊ฒ์ ๋๋ค.
๋๋ ์ค์ง props์ ์ํด์๋ง ๊ตฌ๋๋๊ณ Redux์ ๋ํํ์ง ์๋ ์บก์ํ ๋ React ์ปดํฌ๋ํธ๋ฅผ components
๋ผ๊ณ ๋ถ๋ฆ
๋๋ค. "๋จ์ํ ๊ตฌ์ฑ ์์"์ ๋์ผํฉ๋๋ค. ๋ผ์ฐํฐ, ๋ฐ์ดํฐ ๊ฐ์ ธ ์ค๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฑ์ ๊ด๊ณ์์ด ๋์ผํ๊ฒ ์ ์ง๋์ด์ผํฉ๋๋ค.
Redux, Router ๋ฑ์ ์ธ์ํ๋ React ๊ตฌ์ฑ ์์๋ฅผ containers
๋ผ๊ณ ๋ถ๋ฆ
๋๋ค. ์ด๋ค์ ์ฑ๊ณผ ๋ ๋ง์ด ์ฐ๊ฒฐ๋ฉ๋๋ค. "์ค๋งํธ ๊ตฌ์ฑ ์์"์ ๋์ผํฉ๋๋ค.
@gaearon : ์๋ฒฝํฉ๋๋ค. ๊ทธ ์๊ฐ ๋ช ํ ํด์ง๋๋ค. ๊ฐ์ฌํฉ๋๋ค.
@gaearon ๋ฐ๋ผ์ "dumb ๊ตฌ์ฑ ์์"๋ ์ํ ๋น ์ ์ฅ ๊ตฌ์ฑ ์์๋ก, React 0.14 ์ดํ ๋ ๊ฐ๋จํ ๊ตฌ๋ฌธ ์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
var Aquarium = (props) => {
var fish = getFish(props.species);
return <Tank>{fish}</Tank>;
};
์ ๊ฐ ๋ง์ต๋๊น?
@soulmachine ๋ต.
๋ฐ๋์ ๊ทธ๋ฐ ๊ฒ์ ์๋๋๋ค. ๊ตฌ๋ฌธ์ ์์ ์ด ์๋๋๋ค.
"Dumb"์ปดํฌ๋ํธ๋ "presentational"์ปดํฌ๋ํธ๋ผ๊ณ ๋ํ๋ฉฐ props๋ก ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ณ Redux๋ฅผ ์ธ์ํ์ง ์๊ณ ๋ชจ์ ๋ง ์ง์ ํ๊ณ ๋์์ ์ง์ ํ์ง ์๋ ์ปดํฌ๋ํธ์ ๋๋ค.
@theaqua @gaearon ๊ฐ์ฌํฉ๋๋ค!
"์ปจํ ์ด๋"๋ผ๋ ์ฉ์ด๋ react / redux ๋ช ๋ช ๋ฒ์์ ์ด๋ฏธ ๊ฝค ์ธ๊ธฐ๊ฐ ์์ง๋ง, ๋ ์ด์์ / ๊ทธ๋ํฝ ์ปจํ ์ด๋์์ ํผ๋์ ํผํ๊ธฐ ์ํด ์ ๊ฐ ์์ ์ค์ธ ํ๋ก์ ํธ์์ "์ปค๋ฅํฐ"๋ผ๊ณ ๋ถ๋ฅด๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
btw, ๊ทธ๋ค์ ํธ์ถํ๋ ๋ฐฉ๋ฒ์ ์์ rackt / react-redux # 170์์ ๋
ผ์๋์์ต๋๋ค. ๋ชจ๋ ๊ฒ์ components
ํด๋์ ๋ณด๊ดํ๊ณ ํ๋ฆฌ์ ํ
์ด์
ํด๋๋ components/presentational
์์ ํ ๋จ๊ณ ๋ ๊น๊ฒ ๋ณด๊ดํฉ๋๋ค. ์ปจํ
์ด๋๊ฐ ์๋ ์ฑ์ ์ผ๋ถ์์ ํ์ํ์ง ์๊ธฐ ๋๋ฌธ์ ๊ด์ฐฎ๋ค๊ณ ์๊ฐํฉ๋๋ค.
@gaearon dispatch
"๋ฉ์ฒญํ"๋๋ "์ค๋งํธ ํ"๊ฒ์ผ๋ก ๊ฐ์ฃผ๋๋ ๊ตฌ์ฑ ์์์
๋๊น? ํนํ ๋์คํจ์น๋ฅผ โโ์ํํ๊ธฐ ์ํด ์ด๋ฒคํธ๋ฅผ ๋งจ ์ ๊ตฌ์ฑ ์์๋ก ๋ฒ๋ธ ๋งํ๋ ๋์ ์์
์ ๋์คํจ์นํ๋ ๋ฆฌํ ๋๋ ์ค๊ฐ ๊ตฌ์ฑ ์์๋ฅผ ๊ฐ๋ ๊ฒ์ด ์ ์ฉํฉ๋๋ค.
์, connect()
์ด๋ฌํ ๊ตฌ์ฑ ์์๋ฅผ ์ ํธํ์ง๋ง ๊ฐ๋ ์ ์ฉ ํ ์ ์์ผ๋ฏ๋ก ์ก์
์ ์์๋ ์ํ์ผ๋ก ์ฃผ์
๋ฉ๋๋ค. ์ด๋ป๊ฒ ๋ถ๋ฅด๋์ง๋ ์ค์ํ์ง ์์ต๋๋ค. :-)
์ปดํฌ๋ํธ ๋ชจ๋์ ๊ตฌ์ถ ํ ๋๋ ์ด๋ป์ต๋๊น? ์๋ฅผ ๋ค์ด ๋ด๋น๊ฒ์ด์
๋ฉ๋ด <NavMenu>
๋ํด ๋ณ๋์ ๋
ธ๋ ๋ชจ๋์ด ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค. ์ฌ๋๋ค์ด ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ๋ฅผ ์ํฉ๋๋ค.
import {NavMenu} from 'my-redux-aware-components';
export function myPage(props) {
return (<div><NavMenu routes={props.routes} /></div>);
}
๊ทธ๋์ ์ด๋ฆ์ 'NavMenuContainer'๋ก ์ง์ ํฉ๋๊น? ๊ทธ๊ฒ์ ๋์๊ฒ ์ด์ํด ๋ณด์ธ๋ค. ๋์ ๊ตฌ์ฑ ์์ ์ด๋ฆ์ NavMenuComponent๋ก ์ง์ ํด์ผํฉ๋๊น? ๋ ๋ค ๋์๊ฒ ์ด์ํด ๋ณด์ธ๋ค. ์ด ๊ฒฝ์ฐ ๊ตฌ์ฑ ์์๋ ์ํ์์ ํ๋์ ํ๋๋ฅผ ๊ฐ์ ธ ์ค๊ธฐ ์ํด ์ฐ๊ฒฐ ๋ง ํธ์ถํฉ๋๋ค. ์ด๋ ๊ฒ ์ฐ๊ฒฐํ๊ธฐ ์ํด ํธ์ถ์ ์ธ๋ผ์ธํ๋ ๊ฒ์ด ์ ๋ง ๋์๊ฐ์?
export default const NavMenu = connect(state => ({currentPath:state.routing.path})(React.createClas({...}));
์ปค๋ฅํธ ์ฝ์ ์ธ๋ผ์ธํ๋ ๊ฒ์ด " ๊ด์ฐฎ์ "๋
์ด๋ป๊ฒ ๋ถ๋ฅด๋ ์๊ด ์์ต๋๋ค. NavMenu
๋ผ๊ณ ๋ถ๋ฅด์ง ์๊ฒ ์ต๋๊น?
์ธ๋ผ์ธ์ ๋ํ ์ง๋ฌธ์ ์ดํดํ์ง ๋ชปํฉ๋๋ค.
๋น๊ตํ๋ ๋ ๊ฐ์ง ์ ๊ทผ ๋ฐฉ์์ ์ ์ํ๋ฉด ๋์์ด ๋ ๊ฒ์
๋๋ค.
์๋ฅผ ๋ค๋ฉด ์ข์ต๋๋ค.
์ต์
1 (๋ณ๋์ ํ์ผ 2 ๊ฐ, ์ปจํ
์ด๋ ์ฉ 1 ๊ฐ, ๊ตฌ์ฑ ์์ ์ฉ 1 ๊ฐ)
์ปจํ ์ด๋ / NavMenu
import {connect} from 'react-redux';
import NavMenu from '../components/NavMenu';
export default connect(state => ({currentPath:state.routing.path})(NavMenu);
์ต์
2 (๋ ๋ค ํฌํจํ๋ ๋จ์ผ ํ์ผ 1 ๊ฐ) :
๊ตฌ์ฑ ์์ / NavMenu
import {connect} from 'react-redux';
export default connect(state => ({currentPath:state.routing.path})(React.createClass({
render() {
return <div>the menu {this.props.currentPath} goes here</div>;
}
});
๋ด๊ฐ ์๋ฏธํ๋ ๊ฒ์ ์ํ์์ ํ์ํ currentPath์ ๋ํด ์ฝ๊ฐ๋ง ์๊ธฐ ๋๋ฌธ์ ์ปจํ ์ด๋์ ๊ตฌ์ฑ ์์ ์ธ ๋จ์ผ ํ์ผ (2 ๊ฐ์ ํ์ผ์ด ์๋)์ ๊ฐ๋ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ ํญ์ ํผํด์ผ ํ ์ผ์ ๋๊น, ์๋๋ฉด ์ด์ ๊ฐ์ ๊ฐ๋จํ ๊ฒฝ์ฐ์ ์ํํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ ๋๊น?
๋ฌผ๋ก ๊ฐ๋จํ ๊ฒฝ์ฐ์์ด ์์ ์ ์ํํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ ๋๋ค.
๊ทธ๋์ ์ข์์. ์ธ์ ์ ์ ๊ทธ๋ฆฌ๊ณ "์ข์, ์ด๊ฑธ 2 ๊ฐ์ ํ์ผ๋ก ์ฎ๊ธฐ ๊ฒ ์ด"๋ผ๊ณ ๋งํ๊ฒ ์ต๋๊น?
๊ตฌ์ฑ ์์๊ฐ ๋ฐ์ดํฐ ๋ฌธ์ (๋ฐ์ดํฐ ๊ฒ์ / ๊ณ์ฐ ๋ฐฉ๋ฒ, ์์ ์ ๋ฌ ๋ฐฉ๋ฒ)์ ํ๋ ์ ํ ์ด์ (๋ชจ์)์ ํผํฉํ๊ธฐ ์์ํ ๋. ๋ค๋ฅธ ๋งฅ๋ฝ์์ ํ ์คํธํ๊ฑฐ๋ ์ฌ์ฌ์ฉํ๊ธฐ๊ฐ ์ด๋ ค์ ์ง ๋.
@benmonro ํ ๊ฐ์ง ๋ ์๊ฐํ์ต๋๋ค. ๊ตฌ์ฑ ์์ ๋ชจ๋์ ๋น๋ํ๋ ๊ฒฝ์ฐ ์ด๋ฌํ ๊ตฌ์ฑ ์์๋ฅผ ์ฑ ์ํ ํธ๋ฆฌ์ ๋ค๋ฅธ ๋ถ๋ถ์ ์ฐ๊ฒฐํ๊ฑฐ๋ ๋ค์ํ ์ํ๋ก ํ๋ ์ ํ
์ด์
์ ๊ฐ๋ณ์ ์ผ๋ก ํ
์คํธ ํ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ์ด ๊ตฌ์ฑ ์์ ๋ชจ๋ ๋ด์ connect
์์ผ๋ฉด์ด ๊ธฐ๋ฅ์ด ์ ํ๋ฉ๋๋ค.
๊ฐ์ฌํฉ๋๋ค @gaearon
@sompylasar ์์ฃผ ์ข์ ์ง์ ์ ๋๋ค! ๊ฐ์ฌ
๋ด ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํ์ฌ ๋ถ๋ฆฌ ํ ํ, ์ด์ ํ์ ์ง๋ฌธ์ด ์์ต๋๋ค. <NavMenuItem>
์ปจํ
์ด๋๋ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค. <NavMenu>
๊ตฌ์ฑ ์์๋ <NavMenuItem />
๋ฅผ ํ์ ์์๋ก ์ฐธ์กฐํด์ผํฉ๋๋ค. NavMenu ๊ตฌ์ฑ ์์์์ import NavMenuItem from '../containers/NavMenuItem'
๋ง ์ํํด์ผํฉ๋๊น? ์ด๊ฒ์ด @sompylasar์ ํ
์คํธ ๊ฐ๋ฅ์ฑ์ ์ด๋ค ์ํฅ์ ๋ฏธ์นฉ๋ ๊น?
NavMenuItem์ NavMenu์ ์ํ์ ํตํด ํ์ํ ๋ชจ๋ ๋ฐ์ดํฐ๊ฐ ์ ๋ฌ ๋ ์์ํ ํํ ๊ตฌ์ฑ ์์๋ก ๋ง๋ค ๊ฒ์ ๋๋ค. ์ด๋ฅผ ํตํด ๋ณ๋๋ก ํ ์คํธ ํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ๋ ๊ฐ์ ํ๋ ์ ํ ์ด์ (NavMenu, NavMenuItem) ๋ฐ ํ๋์ ์ฐ๊ฒฐ๋ (connect (...) (NavMenuItem)) ๊ตฌ์ฑ ์์๊ฐ ์์ต๋๋ค.
์ด ํ ๋ก ์์ ๋ด๊ฐ ๋์น ๊ฒ์ ํ๋์ ํ์ผ์ ์์ผ๋ฉด ํ ์คํธ๋ฅผ ์ํด ์์ ๋ ๋๋ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฌ๋๋ค์ด์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํ๋ ์ ํ ์ด์ ๊ตฌ์ฑ ์์์ ์ปจํ ์ด๋ ๊ตฌ์ฑ ์์๋ฅผ ๋ชจ๋ ๋ ธ์ถ ํ ๋ค์ ๊ฐ๋ณ์ ์ผ๋ก ํ ์คํธํ๋ ๊ฒ์ ๋ณด์์ต๋๋ค. ๋ฐ๋ผ์์ด ๊ฒฝ์ฐ ๋ ํ์ผ์ด ๋ ๊ฐ์ง๋ผ๋ ๊ฒ์ ๋ช ์ํ๊ธฐ ์ํด ๋ ๊ฐ์ ํ์ผ์ด ํ์ํฉ๋๋ค. ์ด๊ฒ์ ๋ํ ์ฌ๊ธฐ์ ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ์ ํ๋ฆฌ์ ํ ์ด์ ๊ตฌ์ฑ ์์๊ฐ ๋ ๋ฆฝ์ ์ด๊ณ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๋ค๋ ์ฌ์ค์ ๊ฐ์กฐํฉ๋๋ค.
FWIW ํ์ฌ ์๊ฐ์ ๋ฐ์ํ๊ธฐ ์ํด ํ๋ ์ ํ ์ด์ ๋ฐ ์ปจํ ์ด๋ ๊ตฌ์ฑ ์์ ๋ฌธ์๋ฅผ ์ ๋ฐ์ดํธํ์ต๋๋ค.
์
๋ฐ์ดํธ ๋ ๋ฌธ์์์ ์ปจํ
์ด๋ ๊ตฌ์ฑ ์์๋ฅผ ๋ง๋๋ ๊ฒ์ ๋ ์ด์ ๊ถ์ฅํ์ง ์์ต๋๋ค.
http://redux.js.org/docs/basics/UsageWithReact.html
Redux ๋ฌธ์์ ์ค์ ์์ ์์ @gaearon ์ ๊ตฌ์ฑ ์์๊ฐ ์ปจํ
์ด๋๋ฅผ ์์์ผ๋ก ๊ฐ์ง ์์๋ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค.
๋ด๊ฐ ์๋ชป? ์ด๊ฒ์ด ๋ด๋ถ์์ ๋๋ํ ๊ตฌ์ฑ ์์๋ฅผ ๋ ๋๋งํ๋ ๋ฉ์ฒญํ ๊ตฌ์ฑ ์์์ ํ
์คํธ ๊ฐ๋ฅ์ฑ์ ์ด๋ค ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๊น?
๊ทธ๋ฌ๋ ๊ตฌ์ฑ ์์๋ฅผ ๊ณ์ธต ๊ตฌ์กฐ์ ์ต์ ๊ตฌ์ฑ ์์๋ก ๋ง๋๋ ๋ฐฉ๋ฒ์ ์ฐพ์ง ๋ชปํ์ต๋๋ค.
Simple Data List ๊ตฌ์ฑ ์์ (Dumb)๋ฅผ ๋ ๋๋งํ๋ ์ฑ์ด ์์ต๋๋ค.
๊ทธ ์์๋ ๋ชจ๋ ํญ๋ชฉ์ด ์์ ์ ์ฐ๊ฒฐ๋์ด์ผํ๋ฏ๋ก ์ค๋งํธ ํ ๊ฒ์
๋๋ค.
๋ฌธ์์ ๋ฐ๋ฅด๋ฉด ๊ด์ฐฎ์ง ๋ง ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ต๋๊น?
๊ฐ์ฌ!
์ด๊ฒ์ด ๋ด๋ถ์์ ๋๋ํ ๊ตฌ์ฑ ์์๋ฅผ ๋ ๋๋งํ๋ ๋ฉ์ฒญํ ๊ตฌ์ฑ ์์์ ํ ์คํธ ๊ฐ๋ฅ์ฑ์ ์ด๋ค ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๊น?
์ด๋ก ์ธํด ํ
์คํธ ์ค์ ์ด ์กฐ๊ธ ๋ ์ด๋ ค์์ง๋๋ค (์คํ ์ด๋ ์ด๊ธฐํํด์ผ ํจ). ์ด๊ฒ์ด ๋ถํธํ ๊ฒฝ์ฐ ์ปจํ
์ด๋ ๊ตฌ์ฑ ์์๋ฅผ ๋ด๋ถ๋ก ์ ๋ฌํ ์ ์๋๋ก children
๋ฅผ ํ์ฉํ๋ ๋ ๋ง์ ํ๋ ์ ํ
์ด์
๊ตฌ์ฑ ์์๋ฅผ ์ถ์ถํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋ถ์๋ ๊ทํ์๊ฒ ๋ฌ๋ ค ์์ผ๋ฉฐ ํธ๋ ์ด๋ ์คํ (์์ฑ ์ฉ์ด์ฑ, ๋ฆฌํฉํ ๋ง, ํ
์คํธ ๋ฑ)๋ฅผ ํ๊ฐํ๊ณ ๊ตฌ์ฑ ์์๋ฅผ ๋ถ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์ง์ ์ ํํด์ผํฉ๋๋ค.
์ข์ต๋๋ค. ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ฌ๋ก๋ณ๋ก ํ๊ฐํด์ผํฉ๋๋ค.
๊ฐ์ฌ!!
Il lunedรฌ 2016 ๋
2 ์ 8 ์ผ, Dan Abramov [email protected] ha
์คํฌ ๋ฆฌํ :
์ด๊ฒ์ด ๋ด๋ถ์์ ๋ ๋๋ง๋๋ ๋ฉ์ฒญํ ๊ตฌ์ฑ ์์์ ํ ์คํธ ๊ฐ๋ฅ์ฑ์ ์ด๋ค ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๊น?
๋๋ํ ์ฌ๋?์ด๋ก ์ธํด ํ ์คํธ ์ค์ ์ด ์กฐ๊ธ ๋ ์ด๋ ค์์ง๋๋ค (์ด๊ธฐํํด์ผํฉ๋๋ค.
์์ ๋). ๋ถํธํ ๋ ๋ ์ถ์ถ
์ปจํ ์ด๋๋ฅผ ์ ๋ฌํ ์ ์๋๋ก ์์์ ํ์ฉํ๋ ํ๋ ์ ํ ์ด์ ๊ตฌ์ฑ ์์
๋ด๋ถ ๊ตฌ์ฑ ์์. ์ผ๋ฐ์ ์ผ๋ก ๋ถ์๋ ๊ทํ์๊ฒ ๋ฌ๋ ค ์์ผ๋ฉฐ
ํธ๋ ์ด๋ ์คํ (์์ฑ ์ฉ์ด์ฑ, ๋ฆฌํฉํ ๋ง, ํ ์คํธ ๋ฑ) ํ๊ฐ
๊ตฌ์ฑ ์์๋ฅผ ๋ถ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์ง์ ์ ํํ์ญ์์ค.โ
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ฑฐ๋ GitHub์์ ํ์ธํ์ธ์.
https://github.com/rackt/redux/issues/756#issuecomment -181143304.
๋ฃจ์นด ์ฝ๋ก๋ฌ๋ก
+39345 8948718
๋ฃจ์นด. [email protected]
'๋ ์ด์์ ๊ตฌ์ฑ ์์'๋ ์ด๋ป์ต๋๊น? ๋ผ์ฐํฐ / ๋ด๋น๊ฒ์ดํฐ๋ก ์ ๋ฌํ๊ธฐ ์ํด ๋จ์ผ ๊ตฌ์ฑ ์์์ ์์ด์ผํ๋ ์ปจํ ์ด๋๊ฐ ๋ง์ ๊ฒฝ์ฐ์ด ๋ํ ๊ตฌ์ฑ ์์๋ '์ปจํ ์ด๋์ ๋ฉ์ฒญํ ํํ ์ปจํ ์ด๋'๊ฐ ๋ ๊ฒ์ ๋๋ค.
@ Emilios1995 ๊ฐ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค ...
๋ ์ด์์ ๊ตฌ์ฑ ์์ ๋ด๋ถ์์ ์ฌ์ฉํ๋ ํ์ด์ง ๊ตฌ์ฑ ์์๊ฐ ์์ต๋๋ค.
์ด ๋ ์ด์์ ๊ตฌ์ฑ ์์์๋ ๋ฉ๋ด, ๋จธ๋ฆฌ๊ธ, ๋ฐ๋ฅ ๊ธ์ด ์์ต๋๋ค. ์ฝํ
์ธ ๋ ํ์ด์ง์์ ๋ ์ด์์์ผ๋ก ์ ๋ฌํ ์์์
๋๋ค.
๋ฉ๋ด์ ํค๋๋ ์ปจํ
์ด๋์
๋๋ค !! ๋ฐ๋ผ์ ๋ ์ด์์์ ์ ์ฌ์ ์ผ๋ก ์ปจํ
์ด๋์ด์ง๋ง ์์ ์ ์ฐ๊ฒฐ๋์ง ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๋ฉ๋ด์ ํค๋๋ฅผ ๋ ์ด์์์ผ๋ก ์ ๋ฌํ๋ ค๊ณ ํ๋ฉด ๋ ์ด์์ (๊ตฌ์ฑ ์์)์ ๋ ๋๋งํ๊ณ ๋ฉ๋ด์ ํค๋ (์ปจํ ์ด๋)๋ฅผ ์ ๋ฌํ๋ ํ์ด์ง (์ปจํ ์ด๋)๊ฐ ์์ต๋๋ค.
์ด๋ ๊ฒํ๋ฉด ๊ณ์ธต ๊ตฌ์กฐ๊ฐ ์ ํํ์ง๋ง ๋ชจ๋ ํ์ด์ง์์ ๋ฉ๋ด์ ํค๋๋ฅผ ๋ฐ๋ณตํด์ผํ๋๋ฐ, ๊ทธ ๋นํธ๋ ๋ชจ๋ ํ์ด์ง์์ ๋์ผํฉ๋๋ค.
@LucaColonnello ์ฝ๋ ์์ด๋ ๋ฌธ์ ๋ฅผ ์ดํดํ์ง ๋ชปํฉ๋๋ค. ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๋ ๊ฐ๋จํ ์์ ๋ก StackOverflow ์ง๋ฌธ์ ์์ฑ ํด๋ฌ๋ผ๊ณ ๋ถํํด๋ ๋ ๊น์? ๋๋ ๊ธฐ๋ปํ ๊ฒ์ ๋๋ค.
์ต๋ํ ๋นจ๋ฆฌ
Il sabato 27 2 ์ 2016, Dan Abramov [email protected] ha
์คํฌ ๋ฆฌํ :
@LucaColonnello https://github.com/LucaColonnello ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค
์ฝ๋์์ด ๋ฌธ์ ๋ฅผ ์ดํดํ์ญ์์ค. ๋น์ ์๊ฒ
๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฐ๋จํ ์์ ๊ฐ์๋ StackOverflow ์ง๋ฌธ์ด ์์ต๋๊น? ์ ๋ถ์ฆ
๋ณด๊ณ ๊ธฐ๋ปํ์ญ์์ค.โ
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ฑฐ๋ GitHub์์ ํ์ธํ์ธ์.
https://github.com/reactjs/redux/issues/756#issuecomment -189672067.
๋ฃจ์นด ์ฝ๋ก๋ฌ๋ก
+39345 8948718
๋ฃจ์นด. [email protected]
@gaearon ๊ทธ๊ฒ์ ๋ฌธ์ ๊ฐ ์๋๋ผ ๋ด๊ฐ ์ฌ๊ธฐ์์ ๋ง๋ ์ง๋ฌธ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค : http://stackoverflow.com/questions/35729025/should-the-route-handlers-use-containers-or-presentational-components? noredirect = 1 # comment59133192_35729025
๋งค์ฒด์ ๋ํ Dan์ ๊ธฐ์ฌ
https://medium.com/@dan_abramov/smart -and-dumb-components-7ca2f9a7c7d0 # .3y00gw1mq
๋ชจ๋ ๋ฌธ์ ๋ฅผ ๋ช
ํํํฉ๋๋ค ...
2016-03-01 18:19 GMT + 01 : 00 Emilio Srougo [email protected] :
@gaearon https://github.com/gaearon ๋ฌธ์ ๊ฐ ์๋๋ผ๊ณ ์๊ฐํฉ๋๋ค.
์คํ๋ ค ๋ด๊ฐ ์ฌ๊ธฐ์ ๋ง๋ ์ง๋ฌธ :
http://stackoverflow.com/questions/35729025/should-the-route-handlers-use-containers-or-presentational-components?noredirect=1#comment59133192_35729025โ
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ฑฐ๋ GitHub์์ ํ์ธํ์ธ์.
https://github.com/reactjs/redux/issues/756#issuecomment -190820426.
๋ฃจ์นด ์ฝ๋ก๋ฌ๋ก
+39345 8948718
๋ฃจ์นด. [email protected]
@gaearon ํ๋ ์ ํ
์ด์
๊ตฌ์ฑ ์์์ ์ปจํ
์ด๋ ๊ตฌ์ฑ ์์๊ฐ ํฌํจ๋์ด์๋ ๊ฒฝ์ฐ ์ด๋ป๊ฒ ์ฌ์ฌ์ฉ ํ ์ ์์ต๋๊น?
์ฐธ๊ณ :
ํ๋ ์ ํ ์ด์ ๊ตฌ์ฑ ์์์ ์ปจํ ์ด๋ ๊ตฌ์ฑ ์์๊ฐ ํฌํจ๋์ด์๋ ๊ฒฝ์ฐ ์ด๋ป๊ฒ ์ฌ์ฌ์ฉ ํ ์ ์์๊น์?
๋ชจ๋ ์ฌ์ฉ ์๋๋ฆฌ์ค์ ํน์ ์ปจํ
์ด๋๊ฐ ํฌํจ๋์ด ์๋ค๋ฉด ์ฌ์ฌ์ฉ ํ ์์๋ ๊ฒ์ด ๋ฌด์์ธ์ง ์ ์ ์์ต๋๋ค. ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ this.props.children
์๋ฝํ๊ณ ํน์ ์ปจํ
์ด๋ ๋๋ ํ๋ ์ ํ
์ด์
๊ตฌ์ฑ ์์๋ฅผ ๋ด๋ถ๋ก ์ ๋ฌํ๋ ๋ค๋ฅธ ํ๋ ์ ํ
์ด์
๊ตฌ์ฑ ์์๋ฅผ ๋ง๋ญ๋๋ค.
@gaearon React-Router์ [Root component] ์ปจํ ์ด๋ ์ปดํฌ๋ํธ์ ๋๊น?
<Route path="/" component={Root}>
<IndexRoute component={Main} />
<Route path="/account/signIn" component={SignIn} />
</Route>
export default class Root extends React.Component {
render() {
return (
<div>
<div id="container" className="container">
{this.props.children}
</div>
</div>
);
}
๊ฐ์ฌ.
์์ @gaearon ์ ๋์คํจ์น์ ์ก์ธ์คํ๊ธฐ ์ํด ๊ตฌ์ฑ ์์๋ฅผ ์ฐ๊ฒฐํ๋ ๊ฒ์ ์ ํธํ๋ค๊ณ ๋งํ์ต๋๋ค (๋ถ๋ชจ ๊ตฌ์ฑ ์์์์ ์ ๋ฌํ๋ ๊ฒ๊ณผ๋ ๋ฐ๋๋ก).
์ด ๊ตฌ์ฑ ์์๋ฅผ ์ฐ๊ฒฐํ๊ณ ํ์ฌ ๋ถ๋ชจ๊ฐ ์ ๋ฌํ๋ ๊ฐ์๊ธฐ์์ ๋งคํ ํ ์์๋ props๋ ๊ฐ์ง๊ณ ์๋ค๋ฉด connect
์์ ์ค๋๋ก ๋ฆฌํฉํฐ๋ง ํ์๊ฒ ์ต๋๊น? ๋๋ ownProps
๋ฅผ ์ฌ์ฉํ์ฌ ๋ถ๋ชจ์๊ฒ ์ ๋ฌ๋๋๋กํฉ๋๋ค.
๋ ์ต์ ๊ฐ์ ๊ธฐ๋ฅ / ์ฑ๋ฅ ์ฐจ์ด๊ฐ ์์ต๋๊น?
๋๋ ๊ฑฐ๋ํ redux ํ๋ก์ ํธ ์์ ๊ฒฝํ์ด ๋ง์ง ์์ง๋ง react / redux ํ์ผ ๊ตฌ์กฐ ์ต์ ํ์ ๋ํด ๋ง์ ์ฐ๊ตฌ์ ์๊ฐ์ ํด์์ต๋๋ค. ์ด๊ฒ์ด ์๋ฏธ๊ฐ ์๋์ง ์๋ ค์ฃผ์ญ์์ค.
src/
components/
header/
navigation.js # nav menu list
index.js # Header component
modules/
header/
actions.js # header actions (sticky scroll, collapse mobile menu, etc...)
reducer.js # header actions reducer (export to modules index)
index.js # HeaderContainer (connect to Header component)
index.js # combineReducers and export default configureStore (and middleware)
๋ ๋ค๋ฅธ ๊ฐ๋ :
src/
components/
navigation.js
logo.js
link.js
list.js
item.js
modules/
header/
actions.js # header actions
wrapper.js # header class (smart) component - to wrap header with functionality (was previously classified as container)
container.js # header functional (dumb) component - to contain universal components
index.js # header actions reducer - to export into modules rootReducer
๋๋ ๊ตฌ์ฑ ์์, ์ปจํ ์ด๋ ๋ฐ redux ๋ชจ๋์ ๋ณ๋๋ก ์ ์งํ๋ ๊ฒ์ด ๋ ๋ซ์ต๋๊น (๋์ผํ ์ด๋ฆ์ ๊ณต์ ํ๋๋ผ๋)? ์ ๋ ฅ ํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
์ ๋ ์ํฐํ๋ผ์ด์ฆ ์์ค์ react-redux ํ๋ก์ ํธ๋ก ์์ ํด ์์ผ๋ฉฐ ์ ๊ฒฝํ์ ํตํด ํ๋ก์ ํธ์ ์ํคํ ์ฒ๋ฅผ ์ ์ํ๋ ๋ฐฉ๋ฒ์ ์ ์ ์ผ๋ก ์ฌ๋ฌ๋ถ์๊ฒ ๋ฌ๋ ค ์๋ค๊ณ ๋งํ ์ ์์ต๋๋ค. React์ ๋ชฉ์ ์ด UI ๊ธฐ๋ฐ์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋๋ ๊ฒ์ด๋ผ๋ ์ ์์ ๋น์ค์ฉ์ ์ด๊ธฐ ๋๋ฌธ์ ์ปจํ ์ด๋ / ์ปดํฌ๋ํธ ๊ธฐ๋ฐ ์ํคํ ์ฒ ๋ณํ์ ๋ฐ๋ฅด์ง ์์ต๋๋ค.
๊ทธ๋์ ์ ๋ ๋ชจ๋์ ๊ธฐ๋ฐ์ผ๋ก ์ ์ฒด ํ๋ก์ ํธ๋ฅผ ๊ทธ๋ฃนํํ๋ ๊ฐ๋จํ ์ ๊ทผ ๋ฐฉ์์ ์๊ฐ ํด๋๊ณ ์ง๊ธ๊น์ง ํ์ฅ ์ฑ, ์ ์ง ๋ณด์์ฑ ๋ฐ ์ฝ๋ ๊ฐ๋ ์ฑ ์ธก๋ฉด์์ ์ ๋ง ์ ์๋ํ์ต๋๋ค.
์ ์๊ฒ๋ ์ปจํ
์ด๋์ ์ค๋งํธ ๊ตฌ์ฑ ์์๊ฐ ์ ํํ ๋์ผํฉ๋๋ค. ๊ฐ๋จํ ์ ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ปจํ
์ด๋ / ์ค๋งํธ ์ปดํฌ๋ํธ๋ JSX ๋งํฌ ์
+ ์ด๋ฒคํธ ํธ๋ค๋ฌ + API ํธ์ถ + redux์ ์ฐ๊ฒฐ / MSTP / MSDP๋ฅผ ํฌํจํ๋ ์ปดํฌ๋ํธ์
๋๋ค.
๋ฉ์ฒญํ ๊ตฌ์ฑ ์์๋ ์์ํ๊ฒ ํํ์ ์ด๊ณ ๊ธฐ๋ฅ์ ์ธ ๊ตฌ์ฑ ์์์
๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๋๋ ์ค์ง props์ ์ํด์๋ง ๊ตฌ๋๋๊ณ Redux์ ๋ํํ์ง ์๋ ์บก์ํ ๋ React ์ปดํฌ๋ํธ๋ฅผ
components
๋ผ๊ณ ๋ถ๋ฆ ๋๋ค. "๋จ์ํ ๊ตฌ์ฑ ์์"์ ๋์ผํฉ๋๋ค. ๋ผ์ฐํฐ, ๋ฐ์ดํฐ ๊ฐ์ ธ ์ค๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฑ์ ๊ด๊ณ์์ด ๋์ผํ๊ฒ ์ ์ง๋์ด์ผํฉ๋๋ค.Redux, Router ๋ฑ์ ์ธ์ํ๋ React ๊ตฌ์ฑ ์์๋ฅผ
containers
๋ผ๊ณ ๋ถ๋ฆ ๋๋ค. ์ด๋ค์ ์ฑ๊ณผ ๋ ๋ง์ด ์ฐ๊ฒฐ๋ฉ๋๋ค. "์ค๋งํธ ๊ตฌ์ฑ ์์"์ ๋์ผํฉ๋๋ค.