반응형
Myths about useEffect | Epic React by Kent C. Dodds
TLDR : useEffect는 deps의 상태들과 사이드이펙트를 동기화하기 위한 훅이다.
처음에 리액트를 학습하면 클래스 컴포넌트와 라이프사이클에 대해 배운다.
라이프사이클 함수는 보통 내 코드를 다른사람의 코드 안에 끼워넣는 방법이다.
해당 정보를 의식하고 클래스 컴포넌트처럼 코딩하면 아래처럼 된다.
function DogInfo({dogId}) {
const controllerRef = React.useRef(null)
const [dog, setDog] = React.useState(null)
function fetchDog() {
controllerRef.current?.abort()
controllerRef.current = new AbortController()
getDog(dogId, {signal: controllerRef.current.signal}).then(
(d) => setDog(d),
(error) => {
// handle the error
},
)
}
// didMount
React.useEffect(() => {
fetchDog()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
// didUpdate
const previousDogId = usePrevious(dogId)
useUpdate(() => {
if (previousDogId !== dogId) {
fetchDog()
}
})
// willUnmount
React.useEffect(() => {
return () => {
controllerRef.current?.abort()
}
}, [])
return <div>{/* render dog's info */}</div>
}
function usePrevious(value) {
const ref = useRef()
useEffect(() => {
ref.current = value
}, [value])
return ref.current
}
하지만 실제로 이런 식으로 코딩하지 않는다.
윗 분은 이렇게 말했다 한다.
"어떤 상태와 사이드이펙트를 동기화할 것인가"가 핵심이다.
useEffect(fn) // all state
useEffect(fn, []) // no state
useEffect(fn, [these, states])
그러면 아래와 같이 변경할 수 있다.
function DogInfo({dogId}) {
const [dog, setDog] = React.useState(null)
React.useEffect(() => {
const controller = new AbortController()
getDog(dogId, {signal: controller.signal}).then(
(d) => setDog(d),
(error) => {
// handle the error
},
)
return () => controller.abort()
}, [dogId])
return <div>{/* render dog's info */}</div>
}
useEffect를 주의하여 사용하기
- 의존성 배열 사용 조심하기.
- 변경 시 동기화해야 하는 상태를 배열에 명시적으로 나열한다.
- 성능 문제는 useCallback을 고려한다.
2. useEffect쪼개기
- 상태 - 사이드이펙트의 연관관계를 잘 파악하여 쪼갠다.
function ChatFeed() {
// 사이드이펙트 - 상태 관계를 잘 맺어두어 분리해두면 나중에 분리하기 쉬워진다.
React.useEffect(() => {
// subscribe to feed
return () => {
// unsubscribe from feed
}
})
React.useEffect(() => {
// set document title
return () => {
// restore document title
}
})
React.useEffect(() => {
// subscribe to online status
return () => {
// unsubscribe from online status
}
})
React.useEffect(() => {
// subscribe to geo location
return () => {
// unsubscribe from geo location
}
})
return <div>{/* chat app UI */}</div>
}
// 커스텀 훅으로 뽑아내기
function ChatFeed() {
// NOTE: this is pseudo-code,
// you'd likely need to pass values and assign return values
useFeedSubscription()
useDocumentTitle()
useOnlineStatus()
useGeoLocation()
return <div>{/* chat app UI */}</div>
}
3. useEffect 콜백 내에서 호출할 함수를 정의해야 하는 경우 외부가 아닌 내부에서 정의하라.
- 의존성 배열 관리가 어려워질 수 있음.
참고 : 컴포넌트는 원자고 훅은 전자다. - 댄 아브라모프 -
반응형
'FrontEnd' 카테고리의 다른 글
[Epic React] useDebug으로 custom hook debugging (0) | 2021.12.04 |
---|---|
[Epic React] useLayoutEffect, useImperativeHandle, forwardRef (0) | 2021.12.04 |
[Epic React] useState에서 useReducer로 (0) | 2021.12.03 |
NestJs 관련 학습 컨텐츠 소개 (0) | 2021.12.03 |
[Epic React] form 사용하기 (0) | 2021.12.01 |