Stateless Component & Container

Build React with separation of concerns in mind

reactjavascript

2018-04-16


1. What is it?

UI๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์™€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ํŒจํ„ด์ด๋‹ค. React ๊ณต์‹ ๋ฌธ์„œ์˜ 'Lifting State Up'(๊ณตํ†ต๋œ ์กฐ์ƒ์œผ๋กœ state๋ฅผ ์˜ฌ๋ ค์„œ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ)์˜ ์‘์šฉ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. Separation of concern์„ ๋”ฐ๋ฅด๊ณ  ํŠนํžˆ stateless component์˜ ๊ฒฝ์šฐ, ์žฌ์‚ฌ์šฉ์ด ์šฉ์ดํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

์ถœ์ฒ˜:


2. Stateless component

  1. 'How things look' ์— ๊ด€ํ•œ ๊ฒƒ์ด๋‹ค.
  2. ๋ณดํ†ต state๋‚˜ lifecycle hook์„ ๊ฐ–์ง€ ์•Š๋Š” functional ์ปดํฌ๋„ŒํŠธ์ด๋‹ค. state๊ฐ€ ์žˆ๋‹ค๋ฉด UI์™€ ๊ด€๋ จ๋œ ๊ฒƒ์ด๋‹ค. (ex. toggle) ๊ทธ๋ž˜์„œ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ๋Š” ๋ณดํ†ต Stateless Functional Component๋กœ ์ •์˜ํ•œ๋‹ค.
interface Props {
  name: string
}

export const Hello: React.SFC<Props> = ({ name }) => (
  <div>Hello, {name}!</div>
)
  1. ๋ฐ์ดํ„ฐ์™€ ์ฝœ๋ฐฑ๋„ prop์„ ํ†ตํ•ด์„œ๋งŒ ๋ฐ›๋Š”๋‹ค.

3. Container component

  1. 'How things work' ์— ๊ด€ํ•œ ๊ฒƒ์ด๋‹ค.
  2. ๋ณดํ†ต DOM markup์„ ๊ฐ–์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๊ณ  ๋ณ€๊ฒฝํ•˜๋Š” ์—ญํ• ๋งŒ ๋‹ด๋‹นํ•œ๋‹ค.
  3. class ์ปดํฌ๋„ŒํŠธ๋กœ state๋ฅผ ๊ฐ–๊ณ  ์žˆ์œผ๋ฉฐ ๋ฐ์ดํ„ฐ ์†Œ์Šค์˜ ์—ญํ• ์„ ํ•œ๋‹ค.
  4. ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์— ์ฝœ๋ฐฑ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ prop์œผ๋กœ ๋ณด๋‚ธ๋‹ค. ์ฝœ๋ฐฑํ•จ์ˆ˜๋„ prop์œผ๋กœ ๋˜์ ธ์„œ ์ž์‹ ๋‹จ์—์„œ trigger ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๊ณณ์—์„œ ๋ฐ›์•„์„œ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
interface Props {
  options: string[]
}

interface State {
  selectedOption: string
}

export class SelectOptions extends React.Component<Props, State> {
  state = { selectedOption: null }

  handleSelectOption = (value: string) => this.setState({ selectedOption: value })  // ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝํ•˜๊ธฐ

  render() {
    return (
      <StatelessComponent
        options={this.props.options}  // ๋ฐ์ดํ„ฐ ๋ณด๋‚ด๊ธฐ
        onSelectOption={this.handleSelectOption}  // ์ฝœ๋ฐฑ ๋ณด๋‚ด๊ธฐ
      />
    )
  }
}