useRef의 작동방식
- useRef는 react 컴포넌트에서 mutability(가변성 = 데이터나 객체의 상태가 변경이 가능)를 관리하는데 사용된다.
- useRef로 생성된 객체는 컴포넌트의 생명 주기 동안 유지되며, 리렌더링 시에도 재생성되지 않는다.
- '.current' 프로퍼티를 통해 useRef 객체에 접근할 수 있으며, 이를 통해 값이 변경되어도 리렌더링이 발생하지 않는다.
useRef를 이용하는 것과 그냥 변수를 정의하는 것의 차이
- useRef를 사용하면 값의 변경이 발생하더라도 컴포넌트가 리렌더링되지 않는다. 반면에 상태 변수(State)는 변경 시에 리렌더링을 유발한다.
- 주로 컴포넌트에서의 값의 변경이 화면에 반영되지 않아야 할 때 'useRef'를 사용한다. 예를 들어 DOM 요소에 직접 접근하여 조작할 때 사용될 수 있다.
typescript에서 useRef.current는 null 체크가 필수?
- TypeScript에서는 useRef의 .current가 초기에 null 일 수 있다고 인식한다. 때문에 해당 값에 접근할 때마다 null 체크를 하는 것이 좋다. 그렇지 않으면 경고가 발생할 수 있다.
- 대부분의 경우 입력 양식(form)의 값을 가져오기 위해서는 useRef대신에 상태(State)를 활용하는 것이 더 적절하다. 상태를 사용하면 값이 변경될 때 리렌더링이 발생하므로 UI에 반영이 쉽다 반면 useRef는 주로 DOM 조작 등에서 사용되며, 입력 값에 대한 상태 관리에는 적합하지 않을 수 있다.
react-query 의 QueryClient와 useRef를 함께 사용하는 이유?
- reacr-query에서 QueryClient는 데이터 캐싱 및 관리에 사용된다. useRef는 주로 컴포넌트 내부에서 값의 변경을 추적하거나 DOM에 직접 접근할 때 사용된다. 두 가지를 함께 사용하는 경우는 특별한 경우로, 예를 들어 캐시된 데이터를 직접 참조하거나 조작해야할 때 활용될 수 있다.
import React, { useRef } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
throwOnError: true,
retry: 1,
refetchOnReconnect: true,
refetchOnWindowFocus: false,
staleTime: 60 * 1000,
gcTime: 60 * 1000,
retryDelay: 2000,
},
mutations: {
throwOnError: true,
},
},
});
interface ReactQueryWrapperProps {
children: React.ReactNode;
}
const ReactQueryWrapper = ({ children }: ReactQueryWrapperProps) => {
const queryClientRef = useRef<QueryClient>();
if (!queryClientRef.current) {
queryClientRef.current = queryClient;
}
return (
<QueryClientProvider client={queryClientRef.current}>
<ReactQueryDevtools initialIsOpen={true} />
{children}
</QueryClientProvider>
);
};
export default ReactQueryWrapper;
- queryClient라는 새로운 QueryClient 인스턴스를 생성합니다.
- ReactQueryWrapper 컴포넌트는 queryClientRef라는 useRef를 선언하고 초기값을 undefined로 설정합니다.
- 컴포넌트가 렌더링될 때, queryClientRef의 .current가 undefined이면 현재 생성된 queryClient를 할당합니다.
- QueryClientProvider로 children을 감싸고, 이 프로바이더에 queryClientRef.current를 전달하여 react-query의 컴포넌트들이 동일한 QueryClient를 공유하게 됩니다.
- ReactQueryDevtools를 추가하여 개발 도구를 사용할 수 있게 합니다.
이렇게 함으로써, queryClient가 컴포넌트가 리렌더링될 때마다 새로 생성되지 않고, 한 번 생성된 후에는 계속해서 재사용되게 됩니다. 이러한 패턴은 성능상의 이점이 있을 수 있습니다. 그러나 주의할 점은 QueryClient는 전역으로 사용되므로 상태를 공유하는 컴포넌트들이 예상치 못한 상태 변경이 발생하지 않도록 주의해야 합니다.