useFetcher는 loader나 action이 속한 페이지를 로딩하지 않고 그것들을 실행하고 싶을 때 사용한다.
예를 들어 여러 페이지에서 사용되는 공통된 컴포넌트가 있을 때 뒷단에서 데이터를 받거나 업데이트하려 할 때 유용하다.
const router = createBrowserRouter([
{
path: '/',
element: <RootLayout />,
errorElement: <ErrorPage />,
children: [
{ index: true, element: <HomePage /> },
...
{
path: 'newsletter',
element: <NewsletterPage />,
action: newsletterAction,
},
],
},
]);
만약 라우트 설정이 위와 같고, NewsletterPage가 다음과 같을 때, NewsletterSignup이 제출되면 newsletterAction을 실행하고 싶다고 하자.
function NewsletterPage() {
return (
<PageContent title='Join our awesome newsletter!'>
<NewsletterSignup />
</PageContent>
);
}
export default NewsletterPage;
export async function action({ request }) {
const data = await request.formData();
const email = data.get('email');
// send to backend newsletter server ...
console.log(email);
return { message: 'Signup successful!' };
}
그런데 NewsletterSignup은 RootLayout에 포함되어 모든 라우트에 포함되어 있다고 할 때, 액션을 트리거하고 싶다면 모든 라우트에 그 액션을 추가해야 할 것이다. 이것은 불필요하고 다른 액션과 충돌하게 된다.
이때 react-router-dom에서 제공하는 useFetcher 훅을 사용할 수 있다.
import { useFetcher } from 'react-router-dom';
function NewsletterSignup() {
const fetcher = useFetcher();
...
}
useFetcher는 객체를 리턴하는데 이 객체에는 많은 프로퍼티와 메서드가 포함되어 있다.
return (
<fetcher.Form
method='post'
action='/newsletter'
className={classes.newsletter}
>
<input
type='email'
placeholder='Sign up for newsletter...'
aria-label='Sign up for newsletter'
/>
<button>Sign up</button>
</fetcher.Form>
);
fetcher.Form은 Form 컴포넌트와 같이 실제 action을 실행시키는데, Form과 달리 라우트 전환을 하지 않는다.
따라서 fetcher는 loader나 action을 트리거할 때 그 loader나 action이 속한 페이지로 이동하지 않은 채로 상호작용 하려는 경우에 사용한다.
Form에 action 속성을 추가할 수 있는데, action 속성에 지정한 라우트의 action을 발생시킨다.
즉, 여기서 '/newsletter'로 지정하고 있는데 이것은 newsletter 라우트의 액션을 트리거한다는 의미이다.
만약 fetcher.Form 이 아닌 일반 Form 컴포넌트로 바꾸고 NewsletterSignup을 사용하는 다른 페이지로 가서 폼을 제출한다면, 폼을 제출한 다음에 Newsletter 페이지로 이동된다.
하지만 fetcher.Form을 사용하면 라우트 전환이 일어나지 않기 때문에 Newsletter로 이동하지 않는다.
또한 fetcher가 제공하는 다른 프로퍼티로 사용자에게 피드백을 줄 수 있다.
const { data, state } = fetcher;
useEffect(() => {
if (state === 'idle' && data && data.message) {
alert(data.message);
}
}, [data, state]);
실행된 action 이나 loader가 리턴한 데이터에 data 프로퍼티를 통해 접근할 수 있고, state 값도 받을 수 있다.
useNavigation 훅을 통해 state를 알 수도 있지만, useNavigation은 실제 라우트 변경이 이루어지는 경우에 사용한다.
'React' 카테고리의 다른 글
[React] lazy loading (0) | 2023.09.28 |
---|---|
[React] react-router-dom의 defer (0) | 2023.09.27 |
[React] React Router - action, 데이터 전송하기 (0) | 2023.09.26 |
[React] React Router - loader, useLoaderData로 데이터 가져오기 (0) | 2023.09.26 |
[React] Routing (0) | 2023.09.25 |