막연하게 반대로 생각하고 있었던 부분에 대해서 공식 문서를 기준으로 기록.
https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes
You Might Not Need an Effect – React
The library for web and native user interfaces
react.dev
Adjusting some state when a prop changes
props가 변경될때 state를 수정하는 경우
function List({ items }) {
const [isReverse, setIsReverse] = useState(false);
const [selection, setSelection] = useState(null);
// 🔴 Avoid: Adjusting state on prop change in an Effect
useEffect(() => {
setSelection(null);
}, [items]);
// ...
}
위 코드를 보면 List component가 items를 props로 받고 items가 변경되면 selection을 null로 초기화주는 로직을 useEffect를 통해서 구현했다.
위와 같이 구현하면 items가 변경될때 마다 List component와 자식 component를 모두 rendering 한 후에 DOM에 적용 된 후 effect를 통해서 state가 변경되고 이 과정이 전부 다시 발생한다.
function List({ items }) {
const [isReverse, setIsReverse] = useState(false);
const [selection, setSelection] = useState(null);
// Better: Adjust the state while rendering
const [prevItems, setPrevItems] = useState(items);
if (items !== prevItems) {
setPrevItems(items);
setSelection(null);
}
// ...
}
(함수 안에서 바로 state를 변경하다니 뭔가 이상하다...)
useEffect를 사용한 경우와 달리 위 코드에서는 setSelection은 rendering 과정에서 실행된다. 이 경우 React는 List component가 return 구분을 만나면 즉시 렌더링을 다시 한다. 그 결과 List component의 자식컴포넌트가 다시 render되거나 DOM에 업데이트 되는 과정을 건너뛸 수 있게 된다.
render 과정 중에 update가 발생하면 React는 해당 컴포넌트만 re-render 시킨다. 하지만 대 부분의 경우에는 위 처럼 state를 조작하는 것도 필요가 없다.
function List({ items }) {
const [isReverse, setIsReverse] = useState(false);
const [selectedId, setSelectedId] = useState(null);
// ✅ Best: Calculate everything during rendering
const selection = items.find(item => item.id === selectedId) ?? null;
// ...
}
이런식으로 render 과정 중에 연산을 하는 것이 더욱 성능이 좋다.
무의식적으로 render 과정에서 연산하는 것을 피하고 있었는데 반대로 알고 있었다.
useEffect를 잘 쓰는 방법은 쓰지 않는 거였어..
섞지 않는 거였어
'개발관련 > 리액트' 카테고리의 다른 글
nextjs 14 app router에서 custom api 작성을 위한 Route Handlers (0) | 2024.01.24 |
---|---|
React는 virtual-dom인가? (0) | 2023.08.27 |
react에서 Windowing을 구현해보자 (0) | 2023.08.10 |
[번역] 리액트 기술을 한 단계 업그레이드하세요: 2023년에 마스터할 고급 패턴 5가지 (0) | 2023.08.07 |
리액트 컴포넌트 무한 스크롤 구현 (0) | 2023.05.11 |