Reactivity with SolidJS

Server Action API

Ryan Carniato

Ryan Carniato

SolidJS Creator
Reactivity with SolidJS

Check out a free preview of the full Reactivity with SolidJS course

The "Server Action API" Lesson is part of the full, Reactivity with SolidJS course featured in this preview video. Here's what you'd learn in this lesson:

Ryan demonstrates the progressive enhancement features of the Server Action API. Additional Form elements are used to submit form data to the server when JavaScript isn't enabled. The server-side rendering feature of Solid Start will still display the data correctly.


Transcript from the "Server Action API" Lesson

>> I have one last example that I'm gonna show you that is pretty fitting. It's Todo MVC one last final time, but a different type of Todo MVC than we've seen to date which is pnpm --filter example-todomvc, and I'm gonna just run this straight in dev and build and start.

I'm gonna run this in production mode so we can just see the whole thing as it is. What's special about this todomvc? It's still got a single server out. But what we've done here, essentially is, we've created a route data which is our server data, which gets the gets our todo's from a database.

Except now we're using our server action API's to do mutations, and what this does is we define an action like an addTodo, removeTodo and the implementation of those, I've got them here at the bottom of the file. They basically call our database and they use form data to call our database and then they redirect back to our page.

The redirect probably you're thinking that's kind of weird, but it's because we want these to work even if JavaScript is turned off. So we can define a bunch of actions on our page. Like these are all the todo stuff, things that we implemented earlier. And we can essentially create actions out of these, and what it will give us is both the current state of the form submission like this addingTodo and then the ability to actually submit the form.

It's our same tupple, it's read-write again. And what this lets us do is we could just call the submit method if we wanted to do like a JSON backend. But it also exports a .Form which just gives us our uppercase form component, which here we're seeing it, clear the value and do a little bit of client side validation before it calls our backend.

So without wiring up any URLs or whatnot, we can create multiple forms on the same page. We have addTodo.Form, toggleAll.Form. Again, this is classic like using the input hidden fields. This is classic form kind of stuff, but what's really cool about it is that read state here addingTodo and removingTodo gives us a bit of progressive enhancement.

For example. We iterate over our filtered list of todos like we were doing earlier, but now at the bottom, where is it? We can also iterate over the addingTodo, which are the ones in the pending state, and we're just feeding that form data back into our UI so we can show stuff in a pending status essentially.

If the JavaScript turned off, then who cares? We don't get this like extra enhancement. But let's us do optimistic updates and optimistic UI with progressive enhancement always part of this nice little package and let's take a look and see how that works, okay? It should look familiar to everyone by now, but now let's try and learn solid.

We can see, I'm not a CSS wizard here. You're gonna see like a purple. Well, it's in that pending state. I don't know if you caught that. Let's try that again. Hello World, right? This purple state, just kind of showing like the progressive and you can see the counts and everything updating, let's go.

Active. Completed. Active. And this is just a typical working ToDo example. But what's really cool about this example is if I go to the sources here, and was it sources or network? I couldn't remember which one, I think is sources, I go command P and I go disabled JavaScript.

JavaScript is now disabled. It's no surprising that when I refresh on the page that the server side rendering still works. But what's cool about this is when I do learn solid, you're not gonna see that purple anymore. Saw the page actually refreshing. But, It's still fully working and we can propagate errors this way and redirects and do all our typical actions even when the JavaScript is turned off.

And what's really cool about this is, it's using a combination of these RPC calls. And kind of like the streamlined API so you can make as it's not like your typical HTTP kind of where each page is a location and you have to post. We've kind of broken that rule, you can have ten actions on the same page, you can put your actions in your components not even in your page component.

And this gives us kind of this freedom to kind of define the stuff in JavaScript, the way we're used to when we're building things like single page apps. And yet still have this kind of progressive enhanced experience. And I think one of the really cool things about this approach, though, we're not leveraging it in this demo at all, is that all actions have the ability to, let me see an example of one here, all the, yeah, here.

They also take an option object, so we could do something like this and pass an option. And one of those options could be invalidate it. And we have the ability to say invalidate to this. So we can say when like by default when we do an action it tells all the server data to refresh it, basically, for the page it looks at all the route sections and we don't know what changed, we cannot treat it like a classic MPA, like just refresh the data.

Luckily, underneath our server data or resources that feed into stores so we get those fine grained reconciled updates. But what if we don't wanna reload all the server data every time? Well, we kind of took this kind of progressive approach of remix, mixed it with React query. And those keys that I was playing around with a moment ago when I was doing the route data fetching whereas like setting the key to the source.

Well, they follow a very similar key mechanism to React query where you can use arrays and go like user, user ID and you can do invalidation. And then, it will be smart enough to only refetch the data specifically related to that action. So we kind of decoupled the full page reload experience on top of doing the fine grained updates.

So we think there's a really powerful pattern here for doing both fetching and data mutation. Because it lets you build apps in kind of a classic way in the sense you get the progressive enhancement and you're using the HTML, capital form, capital anchor. But you also get to kind of not get away from modern conveniences like type script safety.

Run those forms through Zod, and kind of mix this together into an experience that we think is really powerful. And that's Solid start today. It's in beta. We're still ironing out bugs. You've seen a couple today probably. But well, it takes a little bit of time Solid JS has been 1.0, it's been in production for the last year now, but Solid start is still a very new project.

We're gonna continue to make improvements on it. And some of those which would be a great demo for another time but I'll link the resources is we have support for partial hydration islands and server components. In fact, the course website that you've been using this today is actually all built with server components, so this is the future for Solid start and for SolidJS in general.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now