Hey,
thanks for the reply! To first answer your questions:
- Was not throwing but returning – honestly had no idea there’s a difference. Seems to be nothing in the internet related to this topic. Unfortunately this did not fix my issue though.
- I’m using the
<Form /> from @remix-run/react. Though I am using through submit(…, { method: “post“ }) from Remix’ useSubmit instead of the “native” form submission. The reason being react-hook-form . I did also try with the native <form /> now that you mentioned it but no luck with that either.
So in short; the issue still persists but I will provide my setup below as thoroughly as possible. I’m sure the solution is simple and I’ve just misconfigured something or doing some weird shenanigans with my Remix & app bridge so please point out any weird patterns you might catch here. Slowly migrating away from @shopify/app-bridge-react and @shopify/polaris has also confused me a little so I might be mix-and-matching or misusing some APIs.
Below are the parts of my app relevant for this question. I’ve removed most of the unrelated code from each snippet for clarity.
app/root.tsx
import { useNavigate } from "@remix-run/react";
const App = () => {
const navigate = useNavigate();
useEffect(() => {
const handleNavigate = (event: any) => {
const href = event.target.getAttribute("href");
if (href) navigate(href);
};
document.addEventListener("shopify:navigate", handleNavigate);
return () => {
document.removeEventListener("shopify:navigate", handleNavigate);
};
}, [navigate]);
return (
<html lang="en">
<head>
<meta name="shopify-api-key" content={SHOPIFY_API_KEY} />
<script src="https://cdn.shopify.com/shopifycloud/app-bridge.js"></script>
<script src="https://cdn.shopify.com/shopifycloud/polaris.js"></script>
</head>
</html>
);
};
app.resources.new/route.tsx
import { Form, useSubmit } from "@remix-run/react";
import { useForm } from "react-hook-form";
export const action = async ({ request }) => {
const { redirect } = await authenticate.admin(request);
--- resource creation & session flash logic ---
throw redirect(`/app/resources/${createdResourceId}`, { headers: { ... } });
}
const NewResourcePage = () => {
const submit = useSubmit();
const { handleSubmit } = useForm();
const onSubmit = (formValues) => submit(formValues, { method: "post" });
return (
<Form onSubmit={handleSubmit(onSubmit)}>...</Form>
);
}
app.resources.$id/route.tsx
import { useNavigate, useLoaderData } from "@remix-run/react";
export const loader = async ({ params, request }) => {
const { redirect } = await authenticate.admin(request);
--- resource fetching & getting session flash ---
return Response.json({ resource, resourceCreated }, { headers: { ... } });
}
const ResourcePage = () => {
const { resource, resourceCreated } = useLoaderData();
const navigate = useNavigate();
useEffect(() => {
if (resourceCreated) {
shopify.toast.show("Resource created!")
// This is where I've tried to do all kinds of navigation things.
// I've tried both taking the resource ID from params as well as
// saving it in the session flash as value and taking it from there
// Been keeping a very close eye on this as well
// console.log(id)
// No errors but nothing happens either.
// navigate("/app/resources/<id>")
// This gives an invalid URL error.
// Source mapping points to a part in the app-bridge.js code where
// shopify:navigation and location.href are manipulated.
// window.navigation.navigate("/app/resources/<id>")
// Hard coding some random id works (updates the browser URL).
// navigate("/app/resources/123")
}
}, [resourceCreated])
...
}
So everything else works except updating the browser URL (and even this works if I hard code some random ID to the destination URL).
ChatGPT and Claude kept telling me the issue lies in the imperative submission of the form through submit(values, { method: "post" }) which led me to try this out without react-hook-form. That did not work either.
Please let me know if you see something alarming in the whole flow of things.
Thank you in advance!