withastro / astro

The web framework for content-driven websites. ⭐️ Star to support our work!
https://astro.build
Other
46.01k stars 2.43k forks source link

[astro:actions]: Error when redirect url in the handler #11613

Closed gitjoshu closed 1 month ago

gitjoshu commented 2 months ago

Astro Info

Astro                    v4.13.1
Node                     v18.20.3
System                   Linux (x64)
Package Manager          unknown
Output                   server
Adapter                  none
Integrations             none

If this issue only occurs in one browser, which browser is a problem?

Chrome

Describe the Bug

When using an astro:action if I redirect to another page it does not work

What's the expected result?

I hope that by using .redirect() it will redirect to another page

Link to Minimal Reproducible Example

https://stackblitz.com/edit/github-wrgjjy?file=src%2Fpages%2Findex.astro,src%2Factions%2Findex.ts,astro.config.mjs,src%2Fpages%2Fhome%2Findex.astro&on=stackblitz

Participation

bholmesdev commented 2 months ago

Hey @gitjoshu! Thanks for reporting. For context: this was an intentional decision to allow JSON-serializable responses from an action rather than complete Response objects. This decision was made when considering client-side action calls. Though for your case using a form POST, I see that a redirect from an action felt intuitive.

For these cases, I would recommend placing the route you want to go on-success in the action path itself, like so:

---
import { actions } from 'astro:actions';
---

<form action={"/home" + actions.login}>

This will navigate to /home and call the action, then render the page with the action result if action succeeds. It will also navigate there when the action raises an exception, though I'm considering a behavior to redirect back to the previous page when an error occurs.

Give this a try and let me know if it resolves your issue.

connor-baer commented 2 months ago

I'm trying to achieve something similar; however, in my case, the redirect URL depends on the action result. Currently, I'm handling the redirect in the component:

// /item/new.astro
const result = Astro.getActionResult(actions.createItem);

if (result?.data) {
  return Astro.redirect(`/item/${result.data.id}`);
}

I first tried to return context.redirect('/item/' + item.id) from the action handler. It's confusing that the method is available on context but doesn't work in this context.

bholmesdev commented 2 months ago

That's a good point @connor-baer. And yes, we recommend redirecting from the page frontmatter rather than the action itself. The thinking there was control; you may want to redirect to a different route depending on what page the action was called from.

There's a few improvements we could make:

gitjoshu commented 1 month ago

Hello @connor-baer @bholmesdev, thank you for your help.

I am currently using the way @connor-baer does it, that is, at the page level, but I have the problem when I want an action to occur with redirect in a react component and it is not a form. In this case I don't know how the implementation would be done.

Example:

const handleRequestEvents = () => actions.requestEvents({ selectedEvents });

Thank you.

bholmesdev commented 1 month ago

@gitjoshu good question! Sounds like you want to redirect on the client. You can use the navigate function from astro:transitions/client for this:

import { navigate } from 'astro:transitions/client';

const result = await actions.example();
if (result && !result.error) {
  navigate("/somewhere");
}

Let me know if that solves your problem.

gitjoshu commented 1 month ago

Thank you @bholmesdev my friend, that's what I wanted for client navigation, I didn't look in the astro transitions documentation, sorry.

Thank you so much for your help as always.