본문 바로가기

FrontEnd

리액트 디자인패턴 : Context Module Function (컨텍스트 모듈 함수 패턴)

반응형

facebook의 코드베이스에서 자주 등장하는 패턴이라 합니다.

Context Module Function 패턴은 유틸리티 함수로 reducer를 감싸는 패턴입니다.

목적 : 사용자에게 dispatch(action)를 숨깁니다.

  • useContext훅은 순수한 dispatch 함수를 넘깁니다.
  • utility함수는 해당 dispatch함수와 파라미터만 넘깁니다.

헬퍼 함수는 분명 다시 구현하게 될 객체 쓰레기입니다. 그냥 dispatch를 사용하세요.

 

Dan on Twitter

“@kentcdodds I intentionally said dispatch 🙂 dispatch is better than helper methods. Helper methods are object junk that we need to recreate and compare for no purpose other than superficially nicer looking syntax. Just use raw dispatch.”

twitter.com

댄 아브라모프가 그렇게 말했다 : 순수 dispatch 함수와 파라미터만을 받는 도우미 함수를 사용하라고 한다.

 

How?

useCallback과 contextValue로 함수를 제공하지 마세요.

const increment = React.useCallback(
  () => dispatch({type: 'increment'}),
  [dispatch],
)
const decrement = React.useCallback(
  () => dispatch({type: 'decrement'}),
  [dispatch],
)
const value = {state, increment, decrement}
return <CounterContext.Provider value={value} {...props} />

그냥 함수를 export하세요. 그리고 해당 함수에서 dispatch를 파라미터로 제공하세요.

컨텍스트 훅에서는 아래와같이 함수와 컨텍스트를 export합니다.

메모이제이션의 불편함과 성능 이슈를 피할 수 있습니다.

// 컨텍스트 모듈
const increment = dispatch => dispatch({type: 'increment'})
const decrement = dispatch => dispatch({type: 'decrement'})

export {CounterProvider, useCounter, increment, decrement}

사용자 컴포넌트는 아래와 같이 dispatch를 파라미터로 전달합니다.

// 컴포넌트 모듈
import {useCounter, increment, decrement} from 'context/counter'

function Counter() {
  const [state, dispatch] = useCounter()
  return (
    <div>
      <div>Current Count: {state.count}</div>
      <button onClick={() => decrement(dispatch)}>-</button>
      <button onClick={() => increment(dispatch)}>+</button>
    </div>
  )
}

이 패턴은 중복을 줄이는 데 도움이 될 뿐만 아니라 성능을 개선하고 종속성 목록의 실수를 방지하는 데 도움이 됩니다.

리덕스 툴킷, 리덕스 액션 크리에이터 등을 사용하지 않는 경우 (Context API나 zustand의 reducer 형태 사용)

큰 도움이 될 듯 합니다.

반응형