React/React 문법

[React]고차 함수 정의 및 React 고차 컴포넌트(HOC)

DevStory 2021. 11. 3.

이번 포스팅에서는 고차 함수와 React 기술 중 하나인 고차 컴포넌트를 소개합니다.

 


고차 함수(HOF) 정의

고차 함수는 아래 두 가지 조건에서 한 가지 조건 또는 모든 조건을 만족하는 함수입니다.

  • 함수를 반환하거나
  • 함수를 인수로 하거나

 

자바스크립트에는 다양한 고차 함수를 지원하는데, 배열에서 사용 가능한 map, filter, sort, reduce 함수가 있습니다.

 

Array.prototype.map()

다음 코드는 배열 numArray을 map 함수를 사용하여 새로운 배열을 생성합니다.

var numArray = [100, 200, 300, 400];

var mapArray = numArray.map(num => num / 2);

console.log(mapArray);
// [50, 100, 150, 200]

map 함수는 함수를 인수로 취하므로 고차 함수입니다. 여기서 num => num / 2는 화살표 함수(Arrow Function)로 작성된 함수입니다.

 

사용자 정의 고차 함수

이번에는 사용자가 직접 고차 함수를 정의합니다.

 

다음은 일반 함수입니다.

var myFunc1 = function(age) { 
  return age * 2; 
}

var myFunc2 = function(age) { 
  return age / 2; 
}

 

다음은 함수를 인수로 취하는 고차 함수입니다.

var hof = function(paramFunc, age) { 
  return paramFunc(age); 
}

고차 함수 hof에 첫 번째 매개변수로 myFunc1 함수를 전달하면, age * 2의 값을 반환합니다. myFunc2 함수를 전달하면, age / 2의 값을 반환합니다.

 

고차 함수 실행 결과


고차 컴포넌트(HOC)

React의 컴포넌트는 함수로 구현할 수 있으므로 "고차 컴포넌트(HOC)"로 불리는 고차 함수를 생성할 수 있습니다.

 

고차 컴포넌트는 컴포넌트를 인수로 취하고 새로운 컴포넌트를 반환하는 함수입니다.

 

예제

다음은 기능이 없는 컴포넌트입니다.

class RegularOneComponent extends React.Component {
  render() {
    return <p>첫 번째 컴포넌트</p>;
  }
}

class RegularTwoComponent extends React.Component {
  render() {
    return <p>두 번째 컴포넌트</p>;
  }
}

 

다음은 컴포넌트를 인수로 취하고 새로운 컴포넌트를 반환하는 고차 컴포넌트입니다.

function AuthWrapper(WrappedComponent) {
  return class extends React.Component {
    render() {
      if (this.props.isLoggedIn) {
        return <WrappedComponent {...this.props} />;
      } else {
        return <p>인증 실패</p>;
      }
    }
  };
}

이 컴포넌트는 props.isLoggedIn이 true이면, 전달받은 컴포넌트를 반환하고 그렇지 않으면 <p>인증 실패</p>를 반환합니다.

 

다음은 일반 컴포넌트를 고차 컴포넌트에 전달하여 새로운 컴포넌트를 반환하는 코드입니다.

const WrappedOne = AuthWrapper(RegularOneComponent);
const WrappedTwo = AuthWrapper(RegularTwoComponent);

 

반환된 컴포넌트를 사용하는 코드입니다.

class App extends React.Component {
  // ...

  render() {
    const { isLoggedIn } = this.state;
    return (
      <div>
        <button onClick={this.toggleAuth}>
          {isLoggedIn ? "Logout" : "Login"}
        </button>
        <WrappedOne isLoggedIn={isLoggedIn} />
        <WrappedTwo isLoggedIn={isLoggedIn} />
      </div>
    );
  }
}

 

지금까지 작성한 코드입니다.

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isLoggedIn: false
    };
  }

  toggleAuth = () => {
    this.setState((prevState, props) => ({
      isLoggedIn: !prevState.isLoggedIn
    }));
  };

  render() {
    const { isLoggedIn } = this.state;
    return (
      <div>
        <button onClick={this.toggleAuth}>
          {isLoggedIn ? "Logout" : "Login"}
        </button>
        <WrappedOne isLoggedIn={isLoggedIn} />
        <WrappedTwo isLoggedIn={isLoggedIn} />
      </div>
    );
  }
}

function AuthWrapper(WrappedComponent) {
  return class extends React.Component {
    render() {
      if (this.props.isLoggedIn) {
        return <WrappedComponent {...this.props} />;
      }
      return <p>인증 실패</p>;
    }
  };
}

class RegularOneComponent extends React.Component {
  render() {
    return <p>첫 번째 컴포넌트</p>;
  }
}

class RegularTwoComponent extends React.Component {
  render() {
    return <p>두 번째 컴포넌트</p>;
  }
}

const WrappedOne = AuthWrapper(RegularOneComponent);
const WrappedTwo = AuthWrapper(RegularTwoComponent);
반응형

댓글