훅은 최상위 레벨에서만 훅을 호출해야 한다
컴포넌트 내에서만 사용가능
훅은 컴포넌트가 렌더링될 때마다 매번 같은 순서로 렌더링되어야 한다
초기값 설정시 무거운 계산이 동반되는 경우 콜백함수로 작성!
🧞♂️ 순서가 상관 없으면 useMemo 순서가 중요하면 useState callback
사용자한테 권한을 주는 것
ref는 컴포넌트 전 생애주기를 통해 유지가 된다.
= 리렌더링되어도 값을 유지
시간과 걸음수가 있을 때 걸음 수에 useRef를 사용하여 값을 유지해야 한다고 생각한다.
걸음수는 하루의 전체 걸음수를 표시해주어야 하기 때문에 리렌더링이 발생한다고 값이 사라지면 안 되고 계속 누적되어 나중에 결과를 표시해주어야 하기 때문이다
context를 이용하면 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있다
예측 가능한 상태 관리: Redux는 애플리케이션 전체의 전역 상태를 중앙 집중식으로 저장하고 관리합니다.
단일 스토어: Redux는 단일 스토어를 사용하며, 앱의 상태를 여러 개의 리듀서로 분할하여 관리합니다.
불변성 유지: Redux는 불변성을 유지하며, 상태를 변경할 때 항상 새로운 상태 객체를 반환합니다.
Middleware: 미들웨어를 사용하여 액션과 리듀서 사이에 추가 기능을 삽입할 수 있습니다. 예를 들어, 비동기 작업을 처리할 수 있습니다.
Redux DevTools: Redux는 강력한 개발 도구를 제공하여 애플리케이션 상태의 시간 여행 및 디버깅을 용이하게 합니다.
로컬 상태 관리: React의 Context API는 주로 특정 컴포넌트 트리 내에서 데이터를 공유하기 위한 용도로 사용됩니다.
하위 컴포넌트에 전달: Context를 사용하여 값을 전달하면 해당 값에 접근할 수 있는 컴포넌트는 해당 Context를 구독하고 있는 컴포넌트 뿐입니다.
간편한 사용: 상대적으로 Redux보다 더 간단하게 사용됩니다. 주로 특정 컴포넌트 간의 데이터 전달이 목적입니다.
적은 양의 데이터 전달: 일반적으로 Redux보다는 소규모 애플리케이션이나 단순한 데이터 전달에 사용됩니다.
const Foo = () => {
const [count, setCount] = useState(0);
// case 1
const handleIncrement = useCallback(() => {
setCount(count + 1);
}, []);
// case 2
const handleIncrement = () => {
setCount(count + 1);
};
return <Box *onClick*={handleIncrement} />;
};
case1과 case2 중에 비용이 적게 드는 코드는 어느쪽일까? 많은 아티클에서 inline
함수는 useCallback
으로 안에 넣는 것이 성능에 더 좋다 말하고 있기 때문에 case1을 선택할 수 있겠지만 실상은 그렇지 않다. 모든 추상화 및 최적화 코드에는 비용이 들기 마련이다. 이때 발생하는 비용을 상쇄 시킬만한 비용절약이 있지 않으면 오히려 비용 증가가 일어난다. 최적화 관점에서 useCallback
을 사용하기 위해선 전후 성능을 비교 후에 사용하는 것이 옳다.useCallback
과 useMemo
를 성능을 향상시킨다는 초점에 맞춰서 무분별하게 사용한다면??dependencies
배열에 들어가는 참조 value
들이 누락되거나 잘못 넣게되면서 휴먼 에러가 자주 발생합니다.dependencies
배열 내부의 값들이 메모제이션되면서 가비지 컬랙터가 안되게 만들 수 있습니다.useCallback
과 useMemo
를 사용하여 성능 개선을 통해 얻어지는 이점이 추가된 비용을 상쇄할 수 있다면 의미있게 사용할 수 있지 않을까? 생각합니다!useState와 비슷하지만 복잡한 상태(중첩된 객체 nested object)를 관리하는데 사용
또는 이전상태에 의존하는 상태를 관리하는데 사용
useReducer
는 React에서 제공하는 훅 중 하나로, 상태 관리를 위해 사용됩니다. 기존의 useState
와 달리, 복잡한 상태 논리를 처리하고 상태를 업데이트하기 위한 더 구조화된 방법을 제공(이전 상태, 액션) => 새로운 상태
의 형태를 갖습니다. 여기서 "액션"은 상태를 어떻게 변경할지에 대한 정보를 가지고 있습니다.dispatch
함수는 Reducer에게 상태를 변경하라는 명령을 내리는 함수입니다. 액션 객체를 인자로 받아 Reducer에게 전달하고, Reducer가 이에 따라 상태를 업데이트합니다.(Hint 순수함수)
useReducer
에서 액션을 처리할 때 주의해야 할 점 중 하나는 순수 함수를 사용해야 한다는 것입니다. 순수 함수란 다음과 같은 특징을 갖는 함수를 의미합니다:부수 효과(side effects)가 없어야 합니다: 순수 함수는 함수 내부에서 외부의 상태를 변경하거나 외부에 영향을 미치는 작업을 수행해서는 안 됩니다. 외부 상태에 변경을 가하지 않아야 합니다.
동일한 입력에 대해서는 항상 동일한 출력을 반환해야 합니다: 함수는 동일한 인자(입력)에 대해 항상 같은 결과(출력)를 반환해야 합니다. 외부 상태의 변화나 무작위 요소 등이 없어야 합니다.
액션을 처리하는 함수인 리듀서는 순수 함수여야 합니다. 외부의 상태를 변경하면 안 되며, 같은 액션에 대해 항상 같은 결과를 반환해야 합니다. 왜냐하면 useReducer
는 순수 함수인 리듀서를 통해 이전 상태와 액션을 바탕으로 새로운 상태를 반환하는데, 이 규칙을 어겨버리면 예상치 못한 문제가 발생할 수 있습니다.
순수 함수를 유지하여 예측 가능하고 안정적인 상태 업데이트를 보장하면서, 코드의 테스트 용이성도 높아집니다. 따라서 리듀서에서는 순수 함수의 원칙을 준수하여 액션을 처리해야 합니다.
useReducer
를 사용할 때 초기 상태가 복잡한 계산이 필요하거나 지연 초기화해야 할 때, 보통 초기 상태를 계산하는 함수를 사용합니다. 여기서 useReducer
의 초기값으로 함수를 전달할 수 있습니다. 이 함수는 실제 초기 상태를 계산하고 반환하는 역할을 합니다. 이를 통해 초기 상태가 복잡한 계산이 필요한 경우 해당 함수를 호출하여 초기 상태를 반환하도록 할 수 있습니다