Using the data router in React-Router 6 I want to redirect the user from an action, but also I need to return data. Can you do both at the same time?
Redirect works, but no way to send data.
export async function routerAction() {
return redirect("/some-url");
}
Should work, but does not.
export async function routerAction() {
return new Response(JSON.stringify({ foo: "bar" }), {
status: 302,
headers: {
"Content-Type": "application/json; utf-8",
Location: "/some-url",
},
});
}
In my component I try to retrieve the data like this:
function SomeComponent() {
let actionData = useActionData(); // unfortunately, actionData is undefined
}
Based on this answer it would seem that modern browsers simply ignore the message body of 302 responses.
As far as I know, all modern browsers ignore the message body of a 302 in response to a GET or POST and will directly go to the URL as specified in
Location
header.
What I can suggest then is to just return a JSON response which includes the data and redirect target back to the component submitting the action, then use a useEffect
hook to effect an imperative redirect to the target route with the data payload.
Example:
import { json } from 'react-router-dom';
const action = ({ request }) => {
return json({
data: { foo: "bar" },
redirect: "/some-url"
});
};
const ComponentA = () => {
const actionData = useActionData();
const navigate = useNavigate();
useEffect(() => {
if (actionData) {
const { data, redirect } = actionData;
navigate(redirect, { state: data, replace: true });
}
}, [actionData, navigate]);
return (
<>
...
<Form method="post">
...
<button type="submit">Submit</button>
</Form>
</>
);
};
Instead of using the useActionData
hook use the useLocation
hook to access the passed route state.
const SomeComponent = () => {
const { state } = useLocation();
...
};