ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • DoIt 리액트 프로그래밍 정석 (5장)
    프론트엔드 2020. 12. 13. 11:04
    728x90

    4장은 실습과정이어서 생략하고 5장부터 이어서 포스트 하려합니다. 5장은 하이어오더 컴포넌트입니다.

     

      ✔ 커링

       쉽게 이야기 하면 함수의 재활용을 위해 사용하며 함수를 반환하는 함수입니다.

       아래 소스를 보시면 일반 방식은 인자를 한번에 전달받고, 커링으로 구성한 함수를 인자를 나우어 받을 수 있습니다.

       이때의 커링의 장점은 multiplyX(2)를 먼저 실행하고 필요에 따라 추가적인 연산 진행이 가능하다는 점입니다.

    function multiply(a, b) { return a * b; }
    
    function multiplyX(x) {
        return function(a) {
            return multiply(x, a);
        }
    }
    
    const result1 = multiply(2, 3) // 6
    const result2 = multiplyX(2)(3) // 6

     

       커링함수 여러개를 조합해서 사용하는 경우에 대해서 생각해 봅니다.

       커링의 경우에는 적용순서가 오른쪽에서 왼쪽으로 진행되기 때문에 코드의 가독성이 떨어지는 단점이 있습니다.

       이를 위해 compose() 함수를 만들어서 사용해보겠습니다.

       참고적으로 아래 소스를 보시면 인자들을 트릭으로 arguments 배열로 변환해서 사용했습니다.

    const formula = x => addFour(multiplyTree(multiplyTwo(x)));
    // ((x * 2) * 3) + 4
    
    function compose(...funcArr) {
        return funcArr.reduce (
            function (prevFunc, nextFunc) {
                return function(...args) {
                    return nextFunc(prevFunc(...args));
                }
            }, function(k) {return k;}
        );
    }
    
    const formulaWithCompose = compose(multiplyTwo, multiplyThree, addFour);
    // ((x * 2) * 3) + 4

     

      ✔ 데코레이션 패턴

       클래스 간의 종속성 없이 기능만을 공유하는 디자인 패턴으로 기존에 많이 사용하는 상속 패턴의 단점을 대신합니다.

       자바스크립트에서 위의 패턴을 구성하려면 앞서 알아본 커링을 사용합니다.

     

      ✔ 하이어오더 컴포넌트

       커링과 거이 비슷한 개념이로 기존 컴포넌트에 기능을 덧입혀 새 컴포넌트를 반환하는 함수를 말합니다.

       하이어오더 컴포넌트는 기존 컴포넌트에 연결된 props를 모두 전달해야하며, 이름은 with ~ 로 명명합니다.

       아래 소스를 보면 하이어오더 컴포넌트는 기본적으로 인자를 하니씩만 가질 수 있기에 다중 커링을 진행하였으며,

       isLoading에 따라 반환값을 분기합니다.

    export default function(loadingMessage = '로딩 중') {
        return function withLoading(WrappedComponent) {
        	const { displayName, name: componentName } = WrappedComponent;
            const wrappedComponentName = displayName || componentName;
            
            function WithLoading({ isLoading, ...otherProps }) {
                if(isLoading) return loadingMessage;
                return <WrappedComponent {...otherProps} />
            };
        };
        
        withLoading.displayName = `withLoading(${wrappedComponentName})`;
        return withLoading;
    }
    import Text from './text';
    import withLoading from './withLoading';
    
    const TextWithLoading = withLoading('로딩 중!')(Text);
    
    ...
    
    return <TextWithLoading isLoading> Hello React! </TextWithLoading> ;

     

      ✔ 하이어오더 컴포넌트 라이브러리

       recompose는 활용도가 높은 하이어오더 컴포넌트 패턴을 모아둔 라이브러리 입니다.

       최신 리액트에서는 해당 기능들이 대부분 hooks로 구현되어 있고, 라이브러리를 그대로 사용하는 경우에는 

       불필요한 소스들이 추가되어 성능저하 문제가 발생할 수도 있습니다.

       그래도 함수형 컴포넌트 기능확장을 위해선 한번씩 직접 구현해보시는걸 추천드립니다.

     

       recompose - branch

       조건식을 조금 더 편리하게 사용하도록 도와주는 함수입니다.

       처음 인자는 출력조건이 참일 경우의 반환 값, 두번쨰는 거짓일 경우의 반환 값을 의미합니다.

       두번쨰 조건식이 만약 생략된다면 WrappedComponent 그대로는 반환합니다.

    import branch from 'recompose/branch';
    
    export default branch(
        ({isLoading}) => isLoading,
        () => () => <Button disabled> Loading... </Button>,
    )(Button)

       recompose - withState

       함수형 컴포넌트에서 state를 우회적으로 사용할 수 있도록 해줍니다.

       처음 인자는 state로 선언할 값이며, 두번 째는 state를 변경할 수 있는 콜백함수 그리고 마지막은 state의 초기 값입니다.

       리액트 함수형 컴포넌트의 useState hooks와 비슷합니다.

    import branch from 'recompose/withState';
    
    const withCountState = withState('count', 'setCount', 0);

       recompose - lifeCycle

       함수형 컴포넌트에서 생명주기 함수들을 우회적으로 사용할 수 있도록 해줍니다.

       당연하게도 클래스형 컴포넌트에서도 사용가능합니다.

       lifeCycle에는 state 값과 componentDidMount 등과 같은 생명주기 함수를 입력하면 됩니다.

    import lifecycle from 'recompose/lifecycle';
    
    const withLoadData = lifecycle({
        state: { isLoading: true, content: '' },
        componentDidMount: function() { ... }
    });
    
    const pageWithLoadData = withLoadData(Page);
Designed by Tistory.