Introduction to SolidJS
Solid is a React-inspired library focused on performance. What makes it special is that it foregoes the use of a virtual DOM. Instead, it extracts the parts of your components that are reactive so that they run faster. Because it's compiled, it fixes some of the weird things about JSX and lets you program in a way that is familiar but more efficient. It also has the highest satisfaction rating according to the latest State of JS survey. Let's go ahead and build a simple search application with components that will show you some of its popular features.
Project Setup with Vite and Degit
Solid is one of those things that you install with Degit. So what we do is npx and then degit, then we can specify one of the templates. So I'll do the solidjs/templates. I'm going to use the javascript template. Then I'll give this thing a name. I want to call this locally, so I'll call this demo-solid and then hit return.
Once we have that, we'll need to switch over to that directory and then run an npm install command. All right, let's open this up in Visual Studio Code. So let's go ahead and open up a terminal and we'll run an npm run dev command. This will start up a server at localhost:3000. Let's go ahead and open up a window with that and you should get something like this.
Exploring the Starter Project Structure
Let's go over what we get. First is a vite.config.js file. You also get this pnpm lock file. You don't need this if you're using just regular npm, so I'm going to delete that. And of course, we have the package.json with the commands that we're running.
Then we have our index.html file. This is being managed by Vite, so the only input is this index.jsx file. And other than that, there's really just a source folder. Here's where your main application goes. And we have this index.jsx which is our entry point. We're importing a CSS file which is right here, and this is just importing the library.
Cleaning Up the Boilerplate
Plus then importing another module called App and then it's targeting an item with an element of root, which is in the index.html file. And the index.css file is just a regular CSS document. It gets imported by the index.jsx file. And then we have an App.jsx. This is the main module, plus we have this app.module.css. Because we have Vite, we can also do things like import a logo into an object.
Let's go ahead and clean this up for our project. So I'm going to get rid of this header right here, and I'll just leave a single div for right now. I'm also going to get rid of the import of the logo as well as the module.css, then get rid of these files as well. I'll rename my index title. In the index, I'll take out the index.css import.
Adding Basic Styling with Pico.css
Let's go ahead and add a headline in our App.js. Let's go ahead and import the Pico CSS library. So we'll go to that website, we'll go to get started, and we'll copy this link right here. I'll go back into the index.html and I'll just paste this import right here. Let's go ahead and add a class of container. And I did notice a tiny mistake here. This should be 'stargazers'. Let's go ahead and fix that. And let's go back into the App.jsx file.
Managing State with createSignal
So far, if you're coming from React, this should be pretty familiar to you. So let's try something that is unique to Solid.js. We'll start by creating a signal, which is the most basic primitive. First, we'll go ahead and import this from the library. And now in our application, we'll create a new constant, and we'll call it keyword, and we'll also create a setter called setKeyword, and apply this to createSignal and initialize this with an empty value.
Underneath our H1, let's create a paragraph and just output the keyword variable. Now it doesn't yet have a value, so let's go ahead and initialize it with a value. You can see that it outputs the variable right here.
Although createSignal looks similar to a React createEffect, Solid is doing something different. In React, the component is a function that runs each time your state updates, whereas in Solid.js, only the part of the function that changes the state is run. In order to do this, Solid.js compiles your code into optimized JavaScript which doesn't require a virtual DOM to run. This is similar to what Svelte does.
Let's go ahead and add an input field here, and we'll call an event. We'll use our setKeyword method using the event's current target. You can see the two-way data binding and reactivity working just fine.
Fetching Data with createResource
If you want to create a signal using asynchronous requests, use a module called createResource. This will update when the fetch completes.
We'll call up a file called cast.json. To get this file to work, I've already created a public folder with a cast.json file. I'm also going to add some images there. Vite will automatically expose anything in a public folder onto your website.
Rendering Lists with the <For> Component
Although we could use a map function, Solid.js has some specialized components that automatically will manage things for you. Here we're going to use a component called For. We'll put these in an article tag, and then we'll create a div and output the name of each cast member. Here we need to use the function version of the call. And it looks like I missed the period right here.
Creating Reusable Components
Now let's see what it takes to create a component. So I'm going to create one right here at the source folder, and I'll call it Cast. And what I'll do is I'll take some of the stuff from the App.js document. And I'll go ahead and export default here. I'm going to call this component Cast and it's going to receive some props from the main component.
I'll paste my For component in there. And I'll need to go ahead and import For, which I could have also used this in the previous component, but I'll do it here. This needs a return statement here. And I'll put all this For content in here. This isn't going to receive the cast list, it's going to receive from the props an item called list and then everything else is going to be the same.
Let's go back into App.jsx and we'll import this component. And we'll go ahead and call the component. We'll pass along the list in a prop, and we'll pass the cast list call. And we'll pass castList in there. Now you can see that it works just the same, right?
Conditional Rendering with <Show> and <When>
So I'm going to move this keyword into my subcomponent and I'm going to reset it in here so that it doesn't have a value when this first loads. That means I need to pass it to the subcomponent, so I'll do that here in the same way that I did the cast list. I'll pass along keyword and in my subcomponent, I'll put it in a label tag, and I'll receive it through the props using the key parameter.
Now because I've added two tags here, I'm going to need a fragment here in order to print more than one tag. Now you can see that this key is passed along into the subcomponent. Now I can add another one of the special components in Solid.js that will let you show something only when a parameter is met. So I'll do when the keyword exists, I'll go ahead and show this cast member. I'll need to make sure that I add that up here as well. And I'll need to once again use the function version of the call. You can see that nothing shows up until I type in a keyword here.
Implementing Reactive Filtering
Let's go ahead and filter our data based on what we type here on this input. After I receive the data from my JSON file, I'm going to filter it using JavaScript, taking the name parameter, converting it to lowercase, and trying to match it with whatever the keyword is currently. Also convert it to lowercase. That should work right here. The problem is that createResource is only going to execute once unless I add a second parameter.
The second parameter will control when createResource gets executed. If the keyword changes, then the createResource object will be fetched again. And now you can see it's filtering the data.
Using the <Show> Component with a Fallback
The Show component also has this really useful feature called the fallback. This will let me add something when the keyword has no value.
Styling and Final Touches
Let's go ahead and import an image. So we'll go back into this Cast component and we'll add an img tag. Our cast.json file has a slug item that lets you have easy access to the image in the images folder.
And now when you type the name in here, you also get the image.
The framework offers a special version of the style attribute that lets you use an object-like syntax. Notice that I am using quotations at the beginning of the parameters instead of having to type the camel case that you would normally have to use with React. And you can see that the words here are bold. Let's go ahead and add another style here. and we'll go ahead and wrap a div around this for loop that way we can add one more style right here.
And now we have a four-column layout here. Let's go ahead and change this margin to zero. That's looking pretty good.