웹찢남

REACT 10일차 (하이어오더 컴포넌트) 본문

FRONT_END/REACT 공부

REACT 10일차 (하이어오더 컴포넌트)

harry595 2020. 7. 9. 19:11

전에 배운 withstyles 함수에서 우리는 이미 커링을 사용했습니다.

커링이란 반환값이 함수인 디자인 패턴을 말하며 중복된 코드를 반복적으로

입력하지 않고 원하는 기능을 조합하여 적재적소에 사용할 수 있다.

 

커링이란 쉽게 말하면 함수를 반환하는 함수다.

함수의 반환은 쉽게보면 아래와 같다.

 

function mul(a,b){

  return a*b;

}

 

function mulX(x){

  return function(a) {

    return mul(a,x);

  }

}

 

위와 같은 함수가 두개 있다고 할 경우 mulX를 사용하여

아래와 같이 다양한 곱 함수를 만들 수 있다.

const multhree=mulX(3);

const mulfour=mulX(4);

const result1=multhree(3);  //3x3=9

const result2=mulfour(3);    //4x3=12

const result3=mulX(3)(3); //3x3=9

 

바로 위 line을 보면 withStyles(...)(...)이 기억이 날 것이다.

여기서 커링함수의 특징은 인자를 나눠받아 실행할 수 있다는 점이다.

 

근데 만약 커링함수의 구조가 복잡해질경우 가독성이 떨어진다는 단점이 있다.

이에 실무에서는 compose함수를 만들어 형태를 조금 더 단순화 한다.

예를들어 const test=mulX(addX));의 형식에서 const test=compose(mulX,addX)의 형식으로 말이다.

 

위 compose 함수를 만드는 대표적인 방법은 아래와 같다.

function compose() {

  const funcArr=Array.prototype.slice.call(arguments);

  return funcArr.reduce(

    fuction (prevFunc,nextFunc) {

      return function(){

        const args=Array.prototype.slice.call(arguments);    

        return nextFunc(prevFunc.apply(null,args));

      }

    },

    function(k) { return k;}

  );

}

slice 함수를 사용하여 나열형 자료를 배열로 변환하여 이와 같은 함수를 만들어 낸다.

 

일반적으로 우리가 button 클래스를 확장하여 여러 클래스를 만들 때는 

상속이라는 기능을 사용한다. 이때 우리가 상속을 여러번 하고 기능을 공유하면

함수의 관계가 복잡해지고 한 클래스만 수정할라해도 머리가 아프다.

 

 

 

이를 위해서 기존의 구조를 해치지 않고 원하는 기능만 상속받을 수 있게

'데코레이터 패턴'이라는 디자인 패턴이 제안됐다.

 

데코레이터 패턴이란 기본적으로 클래스 간의 종속성 없이 기능만을 공유하는 패턴이다.

이제 위에서 배운 커링을 사용하여 데코레이터 패턴을 적용한 하이어오더 컴포넌트를 생각해보자

 

하이어오더 컴포넌트는 아래와 같이 만든다. 참고로 해당 컴포넌트의 이름이 with로 시작해야한다.

import React from "react";

 

export default function withHoC(WrappedComponent) {

  return class withHoC extends React.Component {

    render() {

      return <WrappedComponent {...this.props} />;

    }

  };

}

 

이걸 어디에 쓰나 생각을 해보면 전 챕터에 만든 Text와 Button을 섞어서 아래처럼 이쁘게 쓸 수 있다.

import React from "react";

import { storiesOf } from "@storybook/react";

 

import Button from "../04/Button";

import Text from "../04/Text";

import withHoC from "../05/withHoC";

 

const ButtonWithHoC = withHoC(Button);

const TextWithHoC = withHoC(Text);

storiesOf("WithHoc"module).addWithJSX("으아악", () => (

  <div>

    <ButtonWithHoC>안녕하세용~!!</ButtonWithHoC>

    <ButtonWithHoC xsmall>추가해보자</ButtonWithHoC>

    <TextWithHoC>안녕하세용~!!</TextWithHoC>

    <TextWithHoC xsmall>추가해보자</TextWithHoC>

  </div>

));

 

 

자 이제 데코레이터 패턴의 느낌을 알 수 있을 것이다. 단순히 기능을 가져다 쓸 수 있어서

참 편리하다. 이제 위에서 배운 커링 기능까지 섞어서 코드를 한 번 짜보자

 

위에서 만든 withHoC과 유사한데 잘 보면 export default function이 나왔다.

이를 통해 loadingMessage를 받는데 다음에 story에서 이를 생각하면 로딩메시지를

withLoading('로딩 메시지')(Text)이런식으로 사용하여 정의 할 수 있다.

 

import React from "react";

 

export default function (loadingMessage = "로딩 중!!!") {

  return function withLoading(WrappedComponent) {

    function WithLoading({ isLoading, ...otherProps }) {

      if (isLoadingreturn loadingMessage;

      return <WrappedComponent {...otherProps} />;

    }

    return WithLoading;

  };

}

 

 

#Story 코드

import React from "react";

import { storiesOf } from "@storybook/react";

 

import Button from "../04/Button";

import Text from "../04/Text";

import withLoading from "../05/withLoading";

 

const ButtonWithLoading = withLoading(<Button disabled>로딩중이에요ㅠㅠ</Button>)(Button);

const TextWithLoading = withLoading("로딩싫어.")(Text);

storiesOf("withLoading"module).addWithJSX("악...", () => (

  <div>

    <ButtonWithLoading>안녕하세용~!!</ButtonWithLoading>

    <ButtonWithLoading isLoading>추가해보자</ButtonWithLoading>

    <TextWithLoading>안녕하세용~!!</TextWithLoading>

    <TextWithLoading isLoading>추가해보자</TextWithLoading>

  </div>

));

 

아 참고로 여기서 생각을 해야하는 것은 loading을 왜 이렇게 하지? 라기 보다는 

단순히 위에서 두개 기능을 섞은 코드라고 보면 될 것같다.

 

책에서는 다음 장에 recompose 라이브러리와 다중 하이어오더 컴포넌트를 설명하는데

책에서 사용빈도가 적다하니 Spring도 공뷰할 예정이라 넘어가도록 하겠습니다...

'FRONT_END > REACT 공부' 카테고리의 다른 글

REACT 12일차 (리덕스)  (1) 2020.07.14
REACT 11일차 (컨텍스트)  (0) 2020.07.10
REACT 9일차 (Style component)  (0) 2020.07.07
REACT 8일차 (material design)  (0) 2020.05.23
REACT 7일차 (스토리 북)  (0) 2020.05.22
Comments