- route에서 데이터를 가져오는 것이 loader라면, 보내는 것은 action이다.
* loader: https://sorrel012.tistory.com/393 참고
1. 데이터를 보내는 페이지(컴포넌트)의 route definition에 adction property를 추가한다.
{ path: 'url', element: <컴포넌트 />, action: () => {
// 데이터 보내기
}},
- action은 함수를 값으로 가진다.
* action함수 처리가 너무 복잡해지기 때문에, 보통 element 컴포넌트에 action함수를 정의한다.
export async function action함수명({request, params}) {
const result = await request.formData();
const 저장할객체명 = {
키(key): result.get('name명'),
};
//데이터 보내기
return redirect('이동할url')
}
- router가 capture해서 forwarding된 request를 잡기 위해 request, params를 받는다.
- redirect() 로 전송 완료 후 페이지 이동을 설정할 수 있다.
2. action을 trigger 한다.
// Form 컴포넌트
<Form method="post">
<input name="name설정" required />
<button>Save</button>
</Form>
- name이 필수로 설정되어 있어야 한다.
- submit하면 server로 바로 전송되는 것이 아니라 우리가 정의한 action으로 전송된다.
- 현재 활성화된 route의 action을 trigger하지 않는다면 action property를 추가하여 다른 route로 보낼 수 있다.
// useSubmit hook
- 프로그래밍적으로 action을 trigger 할 수 있다.
const submit = useSubmit();
submit({제출할 data}, {method});
- 첫 번째 인자인 submit하려는 데이터는 자동으로 formData 객체로 감싸진다.(없으면 null)
- 두 번째 인자에는 form의 property와 같은 option 들을 설정할 수 있다.
~ method, action...
import classes from './EventItem.module.css';
import { Link, useSubmit } from 'react-router-dom';
function EventItem({ event }) {
const submit = useSubmit();
function startDeleteHandler() {
const proceed = window.confirm('Are you sure?');
if (proceed) {
submit(null, { method: 'delete' });
}
}
return (
<article className={classes.event}>
<img src={event.image} alt={event.title} />
<h1>{event.title}</h1>
<time>{event.date}</time>
<p>{event.description}</p>
<menu className={classes.actions}>
<Link to={`edit`}>Edit</Link>
<button onClick={startDeleteHandler}>Delete</button>
</menu>
</article>
);
}
export default EventItem;
import { getEventDetail } from '../plugins/eventAxios';
import { json, redirect, useRouteLoaderData } from 'react-router-dom';
import EventItem from '../components/EventItem';
import axios from 'axios';
function EventDetailPage() {
const event = useRouteLoaderData('event-detail');
return <>{<EventItem event={event} />}</>;
}
export default EventDetailPage;
export async function loader({ request, params }) {
const id = params.eventId;
const data = await getEventDetail(id);
if (data.status === 'FAIL') {
json(
{ message: 'Could not fetch Event detail' },
{
status: 500,
},
);
} else if (data.status === 'SUCCESS') {
return data.result.event;
}
}
export async function action({ params, request }) {
const eventId = params.eventId;
await axios
.request({
method: request.method,
url: `http://localhost:8080/events/${eventId}`,
})
.catch(() => {
throw json({ message: 'Could not delete event.' }, { status: 500 });
});
return redirect('/events');
}
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import RootLayout from './pages/Root';
import Homepage from './pages/Home';
import EventsPage, { loader as eventsLoader } from './pages/Events';
import EventDetailPage, {
action as deleteEventAction,
loader as eventDetailLoader,
} from './pages/EventDetail';
import EditEventPage from './pages/EditEvent';
import NewEventPage, { action as eventAction } from './pages/NewEvent';
import EventsRootLayout from './pages/EventsRoot';
import Error from './pages/Error';
const router = createBrowserRouter([
{
path: '/',
element: <RootLayout />,
errorElement: <Error />,
children: [
{ index: true, element: <Homepage /> },
{
path: 'events',
element: <EventsRootLayout />,
children: [
{
index: true,
element: <EventsPage />,
loader: eventsLoader,
},
{
path: ':eventId',
loader: eventDetailLoader,
id: 'event-detail',
children: [
{
index: true,
element: <EventDetailPage />,
action: deleteEventAction,
},
{ path: 'edit', element: <EditEventPage /> },
],
},
{ path: 'new', element: <NewEventPage />, action: eventAction },
],
},
],
},
]);
function App() {
return <RouterProvider router={router} />;
}
export default App;
// useNavigation
- action에서 데이터를 보내는 중인지 확인할 수 있게 해준다.
const navitgation = useNavigation();
const isSubmitting = navigation.state === 'submitting';
// useActionData
- loader에서 return 값을 useLoaderData()로 받아서 처리하는 것과 마찬가지로, action에서 return 값을 받는다.
- 자주 사용하지는 않지만, 오류를 받아와야 할 때 사용한다.
const data = useActionData();
'클라이언트 > React' 카테고리의 다른 글
[리액트(React)] 인증(Authentication) (0) | 2024.02.22 |
---|---|
[리액트(React)] Router - useFetcher (0) | 2024.02.21 |
[리액트(React)] Router - loader (0) | 2024.02.19 |
[리액트(React)] 동적 Route (0) | 2024.02.18 |
[리액트(React)] 라우터(Router) (0) | 2024.02.17 |