# 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: 컴포넌트 합성 패턴
- 불필요한 프롭 드릴링없이 표현적/선언적인 컴포넌트 만들 수 있음.
- 관심사 분리하고 싶고 커스텀 쉽게 만들고싶을때 유용
- 단점
- 너무 UI자유도가 커서 예상치 못한 행동 유발 가능
- 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: 프롭 제어 패턴
- controlled component로 바꿔주고 외부상태는 single source of truth로 사용되어 유저가 커스텀 로직 삽입하기 용이 (걍 state 직접 관리해야한단 말)
- 단점:
- 사용이 복잡. 직접 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: 커스텀훅 패턴
- 유저에게 더 많은 제어권을 준다
- 단점: 로직이 렌더링하는 부분과 분리되어서 유저는 이를 이어줘야 한다.
const { count, handleIncrement, handleDecrement } = useCounter(0);
# 4. Props Getters Pattern: 프롭스 getter패턴
- 커스텀훅이 통제권에서는 좋지만 이용하기 어려워서 이런 복잡도를 감싸기 위해 시도. 걍 쌩 prop을 넘기는게 아니고 getters의 목록 제공
- 단점: 더 불투명해짐.
const {count, getCounterProps, getIncrementProps... } = useCounter({initial: 0, max: MAX_COUNT});
return (
// 뭐여 이게 안복잡하다고?
<Counter {...getCounterProps()}>
<Counter.Increment icon="plus" {...getIncrementProps} />
</Counter>
)
# 5. State reducer pattern: 상태 리듀서 패턴
- 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>
)
결론: 다 구리네