docs-Custom hooks Chanllenges
공식문서에 있는 challenges
제공하는 sandbox에서 실습 후 기록한다.
1. useCounter
// App.js
import { useCounter } from "./useCounter";
export default function Counter() {
const count = useCounter();
return <h1>Seconds passed: {count}</h1>;
}
// useCounter.js
import { useState, useEffect } from "react";
export function useCounter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setCount((c) => c + 1);
}, 1000);
return () => clearInterval(id);
}, []);
return count;
}
2. Make the counter delay configurable
슬라이더로 조절하는 지연 값을 커스텀 훅에 전달하고, 1000ms를 하드코딩하는 대신 전달된 지연을 사용하도록 카운터 훅을 변경해보자.
3. Extract useInterval out of useCounter
현재 사용 중인 카운터 훅은 두 가지 작업을 수행한다.
간격을 설정하고 간격이 틱될 때마다 상태 변수를 증가시킨다.
간격을 설정하는 로직을 useInterval이라는 별도의 Hook으로 분리하세요. 이 Hook은 두 개의 인수를 받아야 합니다:
onTick callback 및 delay.
원래는 useCounter에서 useEffect로 처리했는데
setInterval을 따로 빼려고 하면 useEffect 째로 빼줘야 함.
훅 규칙에 의해 이런 구조에서는 useEffect가 맨 하위로 가야한다.
4. Fix a resetting interval
이 예에서는 두 개의 개별 간격이 있습니다.
App 컴포넌트는 useCounter를 호출하고, 이 컴포넌트는 useInterval을 호출하여 매초마다 카운터를 업데이트합니다.
그러나 App 컴포넌트는 또한 useInterval을 호출하여 2초마다 페이지 배경색을 임의로 업데이트합니다.
어떤 이유에서인지 페이지 배경을 업데이트하는 콜백이 실행되지 않습니다. 사용 간격 안에 몇 가지 로그를 추가합니다:
로그가 예상한 것과 일치하나요? 일부 이펙트가 불필요하게 재동기화되는 것 같다면 어떤 종속성 때문에 그런 일이 발생하는지 짐작할 수 있나요? 이펙트에서 해당 종속성을 제거할 수 있는 방법이 있나요?
문제를 해결한 후에는 페이지 배경이 2초마다 업데이트될 것으로 예상됩니다.
힌트 : 사용중인 Interval Hook이 이벤트 리스너를 인수로 받아들이는 것 같습니다.
이벤트 리스너가 Effect의 종속성이 될 필요가 없도록 이벤트 리스너를 감싸는 방법을 생각해낼 수 있을까요?
useInterval 내에서 틱 콜백을 effect event에 래핑합니다.
이렇게 하면 Effect의 종속성에서 onTick을 생략할 수 있습니다.
컴포넌트를 다시 렌더링할 때마다 Effect가 다시 동기화되지 않으므로
페이지 배경색 변경 간격이 매초마다 재설정되지 않습니다.
이 변경으로 두 간격이 모두 예상대로 작동하며 서로 간섭하지 않습니다:
callback을 useEffectEvent를 이용해 의존성 배열에서 빼줬는데,
useEffectEvent 사용하지않고 그냥 의존성 배열에서 onTick 빼기만해도 작동한다.
useEffectEvent는 아직 stable version에서는 사용할 수 없다.
비반응 로직을 이펙트 이벤트로 추출할 수 있는 hook이라는 설명이 있는데,
그냥 의존성 배열에서 뺀것과 정확히 어떻게 다른지는 아직 모르겠다.
아무튼 위 코드에서는 의존성 배열에 리렌더 될 조건이 아닌 콜백함수까지 포함되어 있었다는게 핵심으로 보인다.
5. Implement a staggering movement
이 예시에서 usePointerPosition Hook은 현재 포인터 위치를 추적합니다.
커서나 손가락을 영역 위로 이동하면 빨간색 점이 움직임을 따라가는 것을 확인할 수 있습니다.
그 위치는 pos1 변수에 저장됩니다.
실제로는 다섯 개(!)의 다른 빨간색 점이 렌더링되고 있습니다.
현재는 모두 같은 위치에 나타나기 때문에 보이지 않습니다. 이 부분을 수정해야 합니다.
대신 구현하려는 것은 "엇갈린" 움직임입니다.
각 점이 이전 점의 경로를 "따라야" 합니다.
예를 들어 커서를 빠르게 이동하면 첫 번째 점은 즉시 따라가고, 두 번째 점은 약간의 지연을 두고 첫 번째 점을 따라가고,
세 번째 점은 두 번째 점을 따라가는 식으로 시차를 두어야 합니다.
사용 지연된 값 사용자 정의 Hook을 구현해야 합니다.
현재 구현은 제공된 값을 반환합니다. 대신 밀리초 전 지연에서 값을 다시 반환하고 싶습니다.
이를 위해서는 state와 Effect가 필요할 수 있습니다.
사용 지연된 값을 구현하고 나면 점들이 서로 따라 움직이는 것을 볼 수 있을 것입니다.
연쇄적으로 작동..
이 효과는 cleanup이 필요 없다.
cleanup에서 clearTimeout을 호출하면 값이 이미 예약된 타임아웃이 재설정 된다.
동작을 계속 유지하려면 모든 타임아웃이 실행되도록 해야 한다.
Last updated