# 2021년 6월, Monthly I Learned

# 6/15

# 유용한 리액트 패턴 5가지

https://velog.io/@dnr6054/%EC%9C%A0%EC%9A%A9%ED%95%9C-%EB%A6%AC%EC%95%A1%ED%8A%B8-%ED%8C%A8%ED%84%B4-5%EA%B0%80%EC%A7%80

두 가지 기준을 잡고 패턴 평가: 1. 유연성&제어용이성(IoC - Inversion of control) 2. 사용자의 난이도

# 1. Compound Components Pattern: 컴포넌트 합성 패턴

  1. 불필요한 프롭 드릴링없이 표현적/선언적인 컴포넌트 만들 수 있음.
  2. 관심사 분리하고 싶고 커스텀 쉽게 만들고싶을때 유용
  3. 단점
    1. 너무 UI자유도가 커서 예상치 못한 행동 유발 가능
    2. JSX 코드가 길어짐
// 이렇게 prop으로 다 내리는거 말고
<Counter onChange={handleChange} label="label" max={10}/>

// 이렇게 쪼개서 유연한 구조로 쓸 수 있도록
// 대부분의 로직은 Counter컴포넌트에 포함되며, Context API를 통해 states와 handlers를 children 컴포넌트간에 공유
<Counter onChange={handleChange}>
  <Counter.Label>label</Counter.Label>
  <Counter.Count max={10} />
</Counter>

# 2. Control Props Patter: 프롭 제어 패턴

  1. controlled component로 바꿔주고 외부상태는 single source of truth로 사용되어 유저가 커스텀 로직 삽입하기 용이 (걍 state 직접 관리해야한단 말)
  2. 단점:
    1. 사용이 복잡. 직접 useState, handleChange, JSX 모두 관리해야함
const [count, setCount] = useState(0);
const handleChangeCounter = (newCount) => {
  setCount(newCount);
};

<Counter value={count} onChange={handleChange}>
  <Counter.Label>label</Counter.Label>
  <Counter.Count max={10} />
</Counter>;

# 3. Custom hook pattern: 커스텀훅 패턴

  1. 유저에게 더 많은 제어권을 준다
  2. 단점: 로직이 렌더링하는 부분과 분리되어서 유저는 이를 이어줘야 한다.
const { count, handleIncrement, handleDecrement } = useCounter(0);

# 4. Props Getters Pattern: 프롭스 getter패턴

  1. 커스텀훅이 통제권에서는 좋지만 이용하기 어려워서 이런 복잡도를 감싸기 위해 시도. 걍 쌩 prop을 넘기는게 아니고 getters의 목록 제공
  2. 단점: 더 불투명해짐.
const {count, getCounterProps, getIncrementProps... } = useCounter({initial: 0, max: MAX_COUNT});

return (
  // 뭐여 이게 안복잡하다고?
  <Counter {...getCounterProps()}>
    <Counter.Increment icon="plus" {...getIncrementProps} />
  </Counter>
)

# 5. State reducer pattern: 상태 리듀서 패턴

  1. IoC에 있어서는 최고의 패턴. but 유저와 개발자 모두에게 복잡
const reducer = (state, action) => {
  switch (action.type) {
    case "decrement":
      return {count: Math.max(0, state.count - 2)}
  }
}

const {count, handleDecrement, ...} = useCounter({initial: 0, max: 10}, reducer); // 오잉 그럼 useCounter내부 리듀서로직에 "decrement"를 받는다는게 암묵적이자나ㄴ

return (
  <Counter value={count}>
    <Counter.Decrement icon="minus" onClick={handleDecrement}>
  </Counter>
)

결론: 다 구리네