해결된 질문
작성
·
154
0
[셀렉트박스 (3/5) headless #2 hook 적용] 부분에서 getTriggerProps/getListProps 처럼 각 컴포넌트가 필요한 것들을 useCallback으로 감싸고 함수형태로 제공해주셨는데요, 아래처럼 useMemo를 이용해서 객체에 값을 담아서 전달해주는 방식은 다른 걸까요??
const getTriggerProps = useCallback(
() => ({
selectedItem: items[selectedIndex],
toggle,
}),
[selectedIndex, items, toggle]
);
const TriggerpropsValue = useMemo(() => {
return {
selectedItem: items[selectedIndex],
toggle,
};
}, [items, selectedIndex, toggle]);
답변 1
1
경우에 따라 다를 것 같습니다만, 제가 이해하기로는
headless 컴포넌트 적용시에 useMemo가 아닌 useCallback을 적용하는 이유는
컴포넌트간의 렌더링 간섭을 최소화하기 위함이 클 것 같습니다.
const useDropdown = () => {
...
return { getContainerProps, getTriggerProps, ... }
}
const Dropdown = () => {
const { getContainerProps, getTriggerProps } = useDropdown()
return (
<DDContainer {...getContainerProps()}>
<DDTrigger {...getTriggerProps()} />
이렇게 각각의 컴포넌트에 넘겨줄 대상을 함수 호출로 해두면getContainerProps
의 내용이 변경되더라도 getTriggerProps
에는 영향을 주지 않을 것입니다.
반면 각각을 useMemo로 만들 경우에는,
const useDropdown = () => {
...
return { handleKeyDown, selectedItem, toggle, ... }
}
const Dropdown = () => {
const { handleKeyDown, selectedItem, toggle } = useDropdown()
return (
<DDContainer handleKeyDown={handleKeyDown}>
<DDTrigger selectedItem={selectedItem} toggle={toggle} />
이렇게 되어서, handleKeyDown
, selectedItem
, toggle
중 어느 하나만 변경되더라도
모든 컴포넌트가 재렌더링될 것 같습니다.
혹은 다음과 같이 할 수도 있겠는데요,
const useDropdown = () => {
...
return { containerProps, triggerProps }
}
const Dropdown = () => {
const { containerProps, triggerProps } = useDropdown(data)
return (
<DDContainer {...containerProps}>
<DDTrigger {...triggerProps} />
이 경우에는 테스트 해보니 괜찮네요.
다만 테스트하면서 보니, getItemProps
의 경우에는 파라미터를 전달해야 해서 useCallback
을 쓸 수밖에 없더군요.
결론은,
파라미터를 전달해야 하는 경우와 그렇지 않은 경우를 나누어 useCallback
/ useMemo
를 구분 적용하는 것도 괜찮고,
파라미터 필요성을 염두에 두어 일관되게 useCallback
만 사용하는 방법도 좋을 것 같습니다.
상세한 설명 감사합니다. useCallback과 useMemo의 차이가 메모이제이션 할 값이 함수인지/값인지 여부로 알고있었는데, 강의의 경우에서 함수를 통해 그저 값만 반환하는 것 같아서 useCallback/useMemo가 갑자기 혼란스러웠는데, 이 경우에는 파라미터를 염두하기 위해 useCallback을 쓰는 것이군요. 답변 감사합니다!😊