⚛️ Custom Hook Pattern

이도경·2023년 3월 23일
0

fRONTeND

목록 보기
7/14
post-thumbnail

React에는 여러 디자인 패턴들이 있습니다.

  • Compound Components
  • Control Props
  • Props Getters
  • Custom Hook
  • State Reducer

그 중 Custom Hook 패턴을 소개합니다.

Reusable

React에서 Custom Hook 패턴의 대표적인 강점은 재사용성이 높다는것입니다. custom hook는 일반적으로 기능적인 역할을 수행하고, 다른 컴포넌트에서 사용할 수 있는 로직을 담고 있습니다. 이로써 중복 코드를 방지하고 코드의 재사용성을 높일 수 있습니다.

Example

다음은 useCounter 의 Custom Hook 사용 예제입니다.

function Main() {
  const { count, handleIncrement, handleDecrement } = useCounter(0);

  return (
    <>
      <Counter value={count}>
        <Counter.Decrement
          icon={"minus"}
          onClick={handleDecrement}
        />
        <Counter.Label>Counter</Counter.Label>
        <Counter.Count />
        <Counter.Increment
          icon={"plus"}
          onClick={handleIncrement}
        />
      </Counter>
    </>
  );
}

export default Main;

예제 코드를 확인해보면, custom hook useCounter를 이용해 상태 변수와 상태 변경 함수를 제공하고 있고, 이를 Counter 컴포넌트의 하위 컴포넌트로 전달하는 모습을 볼 수 있습니다. Counter 컴포넌트는 그 안에 자식 요소들을 가지며, 해당 요소들에 필요한 상태나 이벤트 핸들러 등을 useCounter 커스텀 훅에서 제공받아 사용합니다.

function Counter({ children, value: count, onChange }) {
  const firstMounded = useRef(true);
  
  useEffect(() => {
    if (!firstMounded.current) {
      onChange && onChange(count);
    }
    firstMounded.current = false;
  }, [count, onChange]);

  return (
    <CounterProvider value={{ count }}>
      {children}
    </CounterProvider>
  );
}

Counter.Count = Count;
Counter.Label = Label;
Counter.Increment = Increment;
Counter.Decrement = Decrement;

export { Counter };

Counter 컴포넌트를 mount하게 되면 useEffect() 를 통해 여러 이벤트 처리합니다. 추가로 Counter.* 으로 자식 컴포넌트 요소를 매칭시켜 확장성을 높였습니다.
추가로, Counter에는 ConterProvider가 사용 되었는데, 이는 context 를 통해 전역적으로 값을 받을 수 있습니다.

const CounterContext = React.createContext(undefined);

function CounterProvider({ children, value }) {
  return (
    <CounterContext.Provider value={value}>{children}</CounterContext.Provider>
  );
}

function useCounterContext() {
  const context = React.useContext(CounterContext);
  if (context === undefined) {
    throw new Error("useCounterContext must be used within a CounterProvider");
  }
  return context;
}

export { CounterProvider, useCounterContext };

참고 자료

react-context-turorial
react-patterns(alexis-regnaud)

profile
안녕하세용

0개의 댓글