๐Ÿ’ป ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ(HOC)(feat. ๋ฆฌ์•กํŠธ ๊ณต์‹๋ฌธ์„œ)

waterglassesยท2022๋…„ 11์›” 18์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
43/50
post-thumbnail

โš ๏ธ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์€ ์˜คํƒ€๋‚˜ ์ž˜๋ชป๋œ ์ •๋ณด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ React์˜ ๊ณ ๊ธ‰ ๊ธฐ์ˆ ์ด๋‹ค. ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” React API์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๋ฉฐ, React์˜ ๊ตฌ์„ฑ์  ํŠน์„ฑ์—์„œ ๋‚˜์˜ค๋Š” ํŒจํ„ด์ด๋‹ค.

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์ ธ์™€ ์ƒˆ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

const EnhancedComponent = higherOrderComponent(WrappedComponent);

์ปดํฌ๋„ŒํŠธ๋Š” props๋ฅผ UI๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐ˜๋ฉด์—, ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

ํšก๋‹จ ๊ด€์‹ฌ์‚ฌ(Cross-Cutting Concerns)์— ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉํ•˜๊ธฐ

๊ทœ๋ชจ๊ฐ€ ํฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋™์ผํ•œ ํŒจํ„ด์ด ๋ฐ˜๋ณต์ ์œผ๋กœ ๋ฐœ์ƒํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž. ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ์ด ๋กœ์ง์„ ํ•œ ๊ณณ์—์„œ ์ •์˜ํ•˜๊ณ  ๋งŽ์€ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋กœ์ง์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ์ถ”์ƒํ™”๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ์— ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹๋‹ค.

DataSourceย ๋ฅผ ๊ตฌ๋…ํ•˜๋Š”ย CommentListย ๋‚˜ย BlogPostย ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ตฌ๋…ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ prop์œผ๋กœ ์ „๋‹ฌ๋ฐ›๋Š” ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ ์ค‘ ํ•˜๋‚˜๋กœ ๋ฐ›๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค.

const CommentListWithSubscription = withSubscription(
  CommentList,
  (DataSource) => DataSource.getComments()
);

const BlogPostWithSubscription = withSubscription(
  BlogPost,
  (DataSource, props) => DataSource.getBlogPost(props.id)
);

์ฒซ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๋ž˜ํ•‘๋œ ์ปดํฌ๋„ŒํŠธ์ด๊ณ , ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” DataSource์™€ ํ˜„์žฌ props๋ฅผ ๊ฐ€์ง€๊ณ  ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ด€์‹ฌ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•œ๋‹ค.

CommentListWithSubscriptionย ๊ณผย BlogPostWithSubscriptionย ๊ฐ€ ๋ Œ๋”๋ง๋  ๋•Œย CommentList
์™€ย BlogPostย ๋Š”ย DataSourceย ์—์„œ ๊ฐ€์žฅ ์ตœ๊ทผ์— ๊ฒ€์ƒ‰๋œ ๋ฐ์ดํ„ฐ๋ฅผย dataย prop์œผ๋กœ ์ „๋‹ฌํ•œ๋‹ค.

// ์ด ํ•จ์ˆ˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๊ณ ..
function withSubscription(WrappedComponent, selectData) {
  // ...๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ...
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.handleChange = this.handleChange.bind(this);
      this.state = {
        data: selectData(DataSource, props)
      };
    }

    componentDidMount() {
      // ... ๊ตฌ๋…์„ ๋‹ด๋‹นํ•˜๊ณ ...
      DataSource.addChangeListener(this.handleChange);
    }

    componentWillUnmount() {
      DataSource.removeChangeListener(this.handleChange);
    }

    handleChange() {
      this.setState({
        data: selectData(DataSource, this.props)
      });
    }

    render() {
      // ... ๋ž˜ํ•‘๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋กœ ๋žœ๋”๋ง
      // ์ปดํฌ๋„ŒํŠธ์— ์ถ”๊ฐ€๋กœ props๋ฅผ ๋‚ด๋ ค์ฃผ๋Š” ๊ฒƒ์— ์ฃผ๋ชฉ!
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  };
}

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ์ž…๋ ฅ๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š์œผ๋ฉฐ ์ƒ์†์„ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ž‘์„ ๋ณต์‚ฌํ•˜์ง€๋„ ์•Š๋Š”๋‹ค. ์˜คํžˆ๋ ค ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ์›๋ณธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ปจํ…Œ์ด๋„ˆ ์ปดํฌ๋„ŒํŠธ๋กœ ํฌ์žฅํ•˜์—ฌ ์กฐํ•ฉํ•œ๋‹ค. ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๊ฐ€ ์ „ํ˜€ ์—†๋Š” ์ˆœ์ˆ˜ ํ•จ์ˆ˜์ด๋‹ค.

์›๋ฒˆ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ๋งˆ์„ธ์š”. ์กฐํ•ฉ(Composition)ํ•˜์„ธ์š”.

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์ปดํฌ๋„ŒํŠธ์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ์ˆ˜์ •ํ•˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.

function logProps(InputComponent) {
  InputComponent.prototype.componentDidUpdate = function(prevProps) {
    console.log('Current props: ', this.props);
    console.log('Previous props: ', prevProps);
  };
  // ์›๋ณธ์˜ ์ž…๋ ฅ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์€ ์ด๋ฏธ ๋ณ€ํ˜•๋˜์—ˆ๋‹ค๋Š” ์ ์„ ์‹œ์‚ฌํ•œ๋‹ค.
  return InputComponent;
}

// EnhancedComponent ๋Š” props๋ฅผ ๋ฐ›์„ ๋•Œ ๋งˆ๋‹ค log๋ฅผ ๋‚จ๊ธด๋‹ค.
const EnhancedComponent = logProps(InputComponent);

์œ„์˜ ์ฝ”๋“œ์—๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

๊ทธ ์ค‘ ํ•˜๋‚˜๋Š” ์ž…๋ ฅ๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ™•์žฅ๋œ ์ปดํฌ๋„ŒํŠธ์™€ ๋ณ„๋„๋กœ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋” ์ค‘์š”ํ•œ ๊ฒƒ์€,ย componentDidUpdate๋ฅผ ๋ณ€ํ˜•ํ•˜๋Š”ย EnhancedComponent์— ๋˜ ๋‹ค๋ฅธ HOC๋ฅผ ์ ์šฉํ•˜๋ฉด ์ฒซ ๋ฒˆ์งธ HOC์˜ ๊ธฐ๋Šฅ์€ ๋ฌด์‹œ๋œ๋‹ค. ์ด HOC๋Š” ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ๊ฐ€ ์—†๋Š” ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ์ž˜๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋ณ€๊ฒฝ๋œ HOC๋Š” ๋ˆ„์ถœ๋œ ์ถ”์ƒํ™”์ž…๋‹ˆ๋‹ค. Consumer๋Š” ๋‹ค๋ฅธ HOC์™€์˜ ์ถฉ๋Œ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•˜์—ฌ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋˜์–ด์žˆ๋Š”์ง€ ๋ฐ˜๋“œ์‹œ ์•Œ์•„์•ผ ํ•œ๋‹ค. HOC๋Š” ๋ณ€๊ฒฝ๋Œ€์‹ ์— ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ปจํ…Œ์ด๋„ˆ ๊ตฌ์„ฑ์š”์†Œ๋กœ ๊ฐ์‹ธ์„œ ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

function logProps(WrappedComponent) {
  return class extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('Current props: ', this.props);
      console.log('Previous props: ', prevProps);
    }
    render() {
      // ๋“ค์–ด์˜จ component๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š” container์ด๋‹ค.
      return <WrappedComponent {...this.props} />;
    }
  }
}

์œ„ ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ์ถฉ๋Œ ๊ฐ€๋Šฅ์„ฑ์„ ํ”ผํ•˜๋ฉด์„œ ํ”„๋กœํ† ํƒ€์ž…์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฒ„์ „๊ณผ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•œ๋‹ค.

์ปจ๋ฒค์…˜: ๋ž˜ํ•‘๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•ด ๊ด€๋ จ์—†๋Š” Props ์ „๋‹ฌํ•˜๊ธฐ

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ์ •์˜๋ฅผ ๊ณผ๊ฐํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค. ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ˜ํ™˜๋œ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ž˜ํ•‘๋œ ์ปดํฌ๋„ŒํŠธ์™€ ๋น„์Šทํ•œ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ํŠน์ • ๊ด€์‹ฌ์‚ฌ์™€ ๊ด€๋ จ์ด ์—†๋Š” props๋ฅผ ํ™œ์šฉํ•ด์•ผ ํ•œ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ Œ๋”๋ง ๋ฉ”์„œ๋“œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.

render() {
  // ์ด HOC์—๋งŒ ํ•ด๋‹น๋˜๋ฏ€๋กœ ์ถ”๊ฐ€๋œ props๋Š” ๊ฑธ๋Ÿฌ๋‚ด์–ด ์ด HOC์— ์ „๋‹ฌ๋˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.
  const { extraProp, ...passThroughProps } = this.props;

  // ์ด Props๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ Status๊ฐ’ ๋˜๋Š” Instance method ์ด๋‹ค.
  const injectedProp = someStateOrInstanceMethod;

  // wrapped component์— props๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
  return (
    <WrappedComponent
      injectedProp={injectedProp}
      {...passThroughProps}
    />
  );
}

์ปจ๋ฒค์…˜: ์กฐํ•ฉ ๊ฐ€๋Šฅ์„ฑ(Composability) ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ๋•Œ๋•Œ๋กœ ๋‹จ์ผ ์ธ์ˆ˜๋กœ ๋ž˜ํ•‘๋œ ์ปดํฌ๋„ŒํŠธ๋งŒ ๋ฐ›์„ ๋•Œ๋„ ์žˆ๋‹ค.

const NavbarWithRouter = withRouter(Navbar);

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

// React Redux์˜ `connect`
const ConnectedComment = connect(commentSelector, commentActions)(CommentList);

์œ„์˜ ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋ถ„ํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

// connect๋Š” ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. 
const enhance = connect(commentListSelector, commentListActions);
// ๋ฐ˜ํ™˜๋œ ํ•จ์ˆ˜๋Š” Redux store์— ์—ฐ๊ฒฐ๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ณ ์ฐจ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ์ด๋‹ค.
const ConnectedComment = enhance(CommentList);

connectย ํ•จ์ˆ˜์— ์˜ํ•ด ๋ฐ˜ํ™˜๋œ ๊ฒƒ๊ณผ ๊ฐ™์€ ๋‹จ์ผ ์ธ์ˆ˜ ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š”ย Component => Componentย ํŠน์ง•์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ถœ๋ ฅ ํƒ€์ž…์ด ์ž…๋ ฅ ํƒ€์ž…๊ณผ ๋™์ผํ•œ ํ•จ์ˆ˜๋Š” ์ •๋ง ์‰ฝ๊ฒŒ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ปจ๋ฒค์…˜: ๊ฐ„๋‹จํ•œ ๋””๋ฒ„๊น…์„ ์œ„ํ•œ ๋””์Šคํ”Œ๋ ˆ์ด ๋„ค์ž„ ์ž‘์„ฑ ๋ฐฉ๋ฒ•

๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์€ HOC์˜ ์ด๋ฆ„์œผ๋กœ ๋‚ด๋ถ€ ์ปดํฌ๋„ŒํŠธ๋ช…์„ ๊ฐ์‹ธ๋Š” ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ HOC์˜ ์ด๋ฆ„์ดย withSubscription์ด๊ณ , HOC ๋‚ด๋ถ€์˜ ์ปดํฌ๋„ŒํŠธ์˜ ์ด๋ฆ„์ดย CommentListย ์ธ ๊ฒฝ์šฐ, ๋””์Šคํ”Œ๋ ˆ์ด ๋„ค์ž„์€ย WithSubscription(CommentList)์„ ์‚ฌ์šฉํ•œ๋‹ค.

unction withSubscription(WrappedComponent) {
  class WithSubscription extends React.Component {/* ... */}
  WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`;
  return WithSubscription;
}

function getDisplayName(WrappedComponent) {
  return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}

์ฆ‰, ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„(์ปดํฌ๋„ŒํŠธ์ด๋ฆ„) ํ˜•์‹์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค. ๋ฆฌ์•กํŠธ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์—์„œ๋Š” ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„ ๋Œ€์‹ ์— ์‹ค์ œ ๋ž˜ํ•‘ํ•  ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„ใ…‡๋ฅด ๋ณด์—ฌ์ค€๋‹ค.

์ฃผ์˜์‚ฌํ•ญ

render ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”

render() {
  // render๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๋ฒ„์ „์˜ EnhancedComponent๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
  // EnhancedComponent1 !== EnhancedComponent2
  const EnhancedComponent = enhance(MyComponent);
  // ๋•Œ๋ฌธ์— ๋งค๋ฒˆ ์ „์ฒด ์„œ๋ธŒํŠธ๋ฆฌ๊ฐ€ ๋งˆ์šดํŠธ ํ•ด์ œ ํ›„ ๋‹ค์‹œ ๋งˆ์šดํŠธ ๋œ๋‹ค!
  return <EnhancedComponent />;
}

์—ฌ๊ธฐ์„œ ์„ฑ๋Šฅ์ƒ์˜ ๋ฌธ์ œ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹ค์‹œ ๋งˆ์šดํŠธ ๋˜๋ฉด์„œ ์ปดํฌ๋„ŒํŠธ์˜ state์™€ ์ปดํฌ๋„ŒํŠธ์˜ ํ•˜์œ„ ํ•ญ๋ชฉ๋“ค์ด ์†์‹ค๋œ๋‹ค. ๋Œ€์‹ ์— ์ปดํฌ๋„ŒํŠธ์˜ ์ •์˜ ๋ฐ”๊นฅ์— HOC๋ฅผ ์ ์šฉํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑ๋˜๋„๋ก ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ํ•ด๋‹น component๋Š” ์—ฌ๋Ÿฌ๋ฒˆ ๋ Œ๋”๋ง์ด ๋˜๋”๋ผ๋„ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•œ๋‹ค.

์ •์  ๋ฉ”์„œ๋“œ๋Š” ๋ฐ˜๋“œ์‹œ ๋”ฐ๋กœ ๋ณต์‚ฌํ•˜์„ธ์š”

์ปดํฌ๋„ŒํŠธ์— HOC๋ฅผ ์ ์šฉํ•˜๋ฉด, ๊ธฐ์กด ์ปดํฌ๋„ŒํŠธ๋Š” ์ปจํ…Œ์ด๋„ˆ์˜ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ฐ์‹ธ์ง„๋‹ค. ์ฆ‰, ์ƒˆ ์ปดํฌ๋„ŒํŠธ๋Š” ๊ธฐ์กด ์ปดํฌ๋„ŒํŠธ์˜ ์ •์  ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๋Š”๋‹ค.

// ์ •์  ํ•จ์ˆ˜๋ฅผ ์ •์˜
WrappedComponent.staticMethod = function() {/*...*/}
// HOC๋ฅผ ์ ์šฉ
const EnhancedComponent = enhance(WrappedComponent);

// ํ–ฅ์ƒ๋œ ์ปดํฌ๋„ŒํŠธ์—๋Š” ์ •์  ๋ฉ”์„œ๋“œ๊ฐ€ ์—†๋‹ค.
typeof EnhancedComponent.staticMethod === 'undefined' // true

์œ„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ฉ”์„œ๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์ „์— ์ปจํ…Œ์ด๋„ˆ์— ๋ณต์‚ฌํ•œ๋‹ค.

function enhance(WrappedComponent) {
  class Enhance extends React.Component {/*...*/}
  // ๋ณต์‚ฌ ํ•  ๋ฉ”์„œ๋“œ๋ฅผ ์ •ํ™•ํžˆ ์•Œ์•„์•ผ ํ•จ
  Enhance.staticMethod = WrappedComponent.staticMethod;
  return Enhance;
}

ref๋Š” ์ „๋‹ฌ๋˜์ง€ ์•Š๋Š”๋‹ค

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ชจ๋“  props๋ฅผ ๋ž˜ํ•‘๋œ ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ์›์น™์ด์ง€๋งŒ, refs์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ปดํฌ๋„ŒํŠธ๊ฐ€ HOC์˜ ๊ฒฐ๊ณผ์ธ ์—˜๋ฆฌ๋จผํŠธ์— ref๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒฝ์šฐ, ref๋Š” ๋ž˜ํ•‘๋œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹Œ ๊ฐ€์žฅ ๋ฐ”๊นฅ์ชฝ ์ปจํ…Œ์ด๋„ˆ ์ปดํฌ๋„ŒํŠธ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

์ฐธ์กฐ โ†’ ๐Ÿ’ป Ref ์ „๋‹ฌํ•˜๊ธฐ(feat. ๋ฆฌ์•กํŠธ ๊ณต์‹๋ฌธ์„œ)

๐Ÿ”ฅ ๋Š๋‚€์ 

๋กœ์ง์„ ํ•œ ๊ณณ์—์„œ ์ •์˜ํ•˜๊ณ  ๋งŽ์€ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋กœ์ง์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ์ถ”์ƒํ™”๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•ด์•ผ๊ฒ ๋‹ค. ์ฆ‰, ํšก๋‹จ ๊ด€์‹ฌ์‚ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ์˜ ์—ญํ• ์ธ ๊ฒƒ์ด๋‹ค.
ํšก๋‹จ ๊ด€์‹ฌ์‚ฌ๋ผ๋Š” ๊ฒƒ๋„ ์ฒ˜์Œ ์•Œ์•˜๊ณ  ์–ด๋–จ ๋•Œ hoc ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š”์ง€ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

Refer

profile
๋งค ์ˆœ๊ฐ„ ์„ฑ์žฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€