Next.js Discord

Discord Forum

Need to trigger a client event after a server action.

Answered
LeonN posted this in #help-forum
Open in Discord
Avatar
I have a form with one field called name. After some validation in a server action, it makes a post request on my API, which will respond with a success or error. If the creation is successful, I want to redirect the user to the root page "/", where my form is. Besides, I want to show a toast message informing the user about the successful result. My toast component is a client component with a global context. How can I trigger the activation of that client component in a server action? I though about returning a success: true on the form action, and in the form, trigger the toast via useEffect tracking the value of the success key of the returned object, but since I want to use the redirect feature on the server action, this won't be possible.
Image
Answered by chisto
you can return a success: true on the form action and redirect in the client component with router.push
 
if(state.sucess){
  toast();
  router.push("somewhere")
}
View full answer

16 Replies

Avatar
Australian Freshwater Crocodile
Where do you call this action? Directly in the action prop of the form?
Avatar
Australian Freshwater Crocodile
a) You could instead use the onSubmit on the form, especially if you need data from the event object it gets passed.
The way we used to do it before actions, then inside the handleSubmit()

1- you start an async transition
2- you call and await the action inside the transition,
3- and after getting the response back from the action, you call the toast()


b) just make an async wrapper for the function you pass to the action prop:

<form action = { async (formData) => { // i assume this "action "is returned from the useActionState hook, right? const response = await action(formData); // call your toast toast() } } >
Avatar
you can return a success: true on the form action and redirect in the client component with router.push
 
if(state.sucess){
  toast();
  router.push("somewhere")
}
Answer
Avatar
@chisto you can return a success: true on the form action and redirect in the client component with router.push if(state.sucess){ toast(); router.push("somewhere") }
Avatar
Australian Freshwater Crocodile
Where would you put this logic in?
a) in the render function of the component who's getting the response back
b) inside a use effect that's listening on the "state" variable returned by the action
c) event handler / action callback

I believe this should be considered a side effect and should be done in either an event handler or an action callback wrapper, this logic is being trigger by some user action, it's not part of the component render or sync logic (IMO this shouldn't synchronize inside an useEffect).
Avatar
I ended up follwing the approach mentioned by @chisto . As my form is already a client component, in my form action I removed the redirect and return a result of type success (custom enum). Via use effect I'm tracking changes in the message, so the snackbar can show it, and I'm adding a conditional to verify if the succes type was true, in that case, I will use client side navigation. My doubt is, if using client side navigation has a difference with the redirect api from server navigation. Is it a performance cost or anything?
Image
Avatar
I'm aware of that. So far, I haven't encountered that issue, since validation errors are displayed in another key of the return object.
Avatar
Australian Freshwater Crocodile
The useEffect won't synchronize, dependencies didn't change since last time it ran... there's a bug there might bite you later
Avatar
@LeonN I'm aware of that. So far, I haven't encountered that issue, since validation errors are displayed in another key of the return object.
Avatar
Australian Freshwater Crocodile
I see, still have that in mind for other use cases
Try to avoid useEffect as much as possible when you have other solutions that make sense, there's even a full article in React docs, soooo long that I would recommend reading, it's called "You Might Not Need an Effect"
Btw I speak spanish too in case you want to talk in private, i'm from Mexico :p
Avatar
Australian Freshwater Crocodile
"Is it a performance cost or anything?"

I don't think there's a cost, although there's a difference in the way they work:
- router.push("/route") works by pushing a new entry in the history stack of the broswer and preventing the router hard refresh, so it can keep the scroll position
- redirect("/route") works by throwing an error 3XX (redirection error), and Next.js is smart enough to catch this error and push a new entry in the browser history, sending you to that URL.
Also, idk if they fixed this already but before if you redirected inside a try{}catch{} it woudn't do anything since the catch block would catch the error lol
Avatar
Thank you for the replies. It is good to know there is no problem with client side routing.