Getting started with SolidJS
Tags: solidjs, react
Published: 2023-02-23 23:55:14

by [Isaac Okoro](https://blog.openreplay.com/authors/isaac-okoro)


[Solid.js](https://www.solidjs.com/)  is an open-source JavaScript library for building web applications focusing on performance and simplicity. It is designed to make it easy for developers to create fast, scalable, and maintainable web applications.

Solid.js is built on top of the React library, providing tools and utilities that make it easier to develop and manage complex React applications. In addition, it offers a lightweight, unopinionated approach to building web applications, allowing developers to choose the libraries and tools that best fit their needs.

Some of the key features of Solid.js include a lightweight component model, a simple and flexible API, server-side rendering, and code-splitting support. It is also designed to be easy to learn and use, making it a good choice for developers new to building web applications.

This tutorial will focus on how to build an application that shows characters from the Rick and Morty series. We will also implement infinite scrolling in this application.

Some prerequisites to follow along in this tutorial include:

- [Node](https://nodejs.org/) installed on your system
- Basic understanding of Javascript and React


## Creating a new SolidJS project

The first step is to create a new SolidJS application by running the command below in the terminal:

```
npx degit solidjs/templates/js rick-and-morty
```

Navigate to the folder and install the application dependencies with the commands below.

```
cd rick-and-morty 
yarn #or npm i or pnpm
```
   

The next step is to run `yarn dev` to start the development server, which opens at `http://localhost:3000/` on your browser.


![1](https://blog.openreplay.com/images/getting-started-with-solid-js/images/image01.png)


We will be using TailwindCSS for styling purposes, which can be installed by following the steps outlined in the Tailwind [documentation](https://tailwindcss.com/docs/guides/solidjs). Below is an image of the file tree structure of a SolidJS application.

![2](https://blog.openreplay.com/images/getting-started-with-solid-js/images/image02.png)



## APIs in SolidJS

Built like React, SolidJS also provides developers with APIs that make building your application a breeze. We will look at some of them in this section.


- `createSignal`: This is SolidJS's default method for handling state and state changes. It comes with a getter and a setter element. The getter returns the current state value while the setter updates the state value. `createSIgnal` work like the `useState` hook in React.

```javascript
import { createSignal } from "solid-js";
    
function App() {
  const [count, setCount] = createSignal(0);
    
  return <div>{count()}</div>
}
```



- `createEffect`:  These are used for handling side effects in your applications. `createEffect` work like the useEffect hook in React.
- `createResource`: This reflects the results of an async function.

You can visit the docs [here](https://www.solidjs.com/docs/latest/api) to find out more about the APIs available in Solid.js.


## Building the application

The application will be divided into two components: The component to show details about each episode and a component to show each character. First, create a component folder and the two files as shown below:

![3](https://blog.openreplay.com/images/getting-started-with-solid-js/images/image03.png)


In the `src/App.jsx` file, clear the boilerplate code and paste the code below into it:


```javascript
import { For, createSignal, onMount, createEffect } from 'solid-js';
import axios from 'axios';
import EpisodeBox from './components/EpisodeBox';

```


In the code block above, we imported various APIs and methods from SolidJS. We now know the uses of the `createSignal` and the `createEffect` APIs. The `onMount` method runs a code after the component has been rendered. The `For`   method eliminates the need for using the `Array.prototype.map()` in looping through an array.

We also installed [axios](https://axios-http.com/), which will be useful for making network requests. Next, add the code below to the `App.jsx` file.

```javascript

// src/App.jsx

// imports remain the same
const fetchEpisodes = async () =>
  await axios.get("https://rickandmortyapi.com/api/episode"); // The API

function App() {
  const [episodes, setEpisodes] = createSignal(null);

  onMount(async () => {
    setEpisodes((await fetchEpisodes()).data);
    console.log(episodes());
  });

  return (
    <>
      <div class="flex justify-center items-center flex-col p-10">
        <h2 class=" font-medium text-4xl my-5">Rick and Morty</h2>
        <div style={{ width: "1000px" }}>
          <For each={episodes()?.results} fallback={<p>Loading...</p>}>
            {(episode) => (
              <div>
                <EpisodeBox episode={episode} />
              </div>
            )}
          </For>
        </div>
      </div>
    </>
  );
}
export default App;

```


In the code block above, we created a function for fetching data from the Rick and Morty API. First, we created a getter and setter signal (for handling state ), naming them `episode` and `setEpisode`. Next, we called the `onMount` method and passed in the data from calling the API into the setter signal. After setting it, we log the getter signal to the console, map through the results using the  `For` method from SolidJS, and then passed the mapped data as props to the `EpisodeBox` component.

Now when we check our console, we should see the results from the API shown below:

![4](https://blog.openreplay.com/images/getting-started-with-solid-js/images/image04.png)



Next, navigate to the `src/components/EpisodeBox.jsx` and paste the code below into it.

```javascript
// src/components/EpisodeBox.jsx

import { createSignal, For } from "solid-js";
import CharacterDetails from "./CharacterDetails";

const EpisodeBox = ({ episode }) => {
  // setting the state for the number of characters to be shown at a time
  const [loadCount, setLoadCount] = createSignal(6);
  // state that will be used check the total page for each episode
  const [counter, setCounter] = createSignal(1);

  // variable that checks the total page
  const totalPage = Math.ceil(episode.characters.length / 6);

  // functionality for checking if more pages are available and then rendering them
  const handleLoadMore = () => {
    if (counter() < totalPage) {
      setLoadCount((prevState) => prevState + 6);
      setCounter((prevState) => prevState + 1);
    }
  };

  // function that checks the episode number
  const episodeNumber = episode.episode.substring(
    episode.episode.length - 2,
    episode.episode.length
  );

  // function that checks the season number
  const seasonNumber = episode.episode.substring(1, 3);
  return (
    <div class="rounded-md border-solid border p-5 border-black mt-5">
      <p className="text-3xl">
        #{episode.id}-{episode.name}
      </p>
      <p className="text-xl my-2">
        {`This is 
              episode ${episodeNumber} in season ${seasonNumber}. It was broadcast on ${episode.air_date}. There are a total of ${episode.characters.length} characters 
              featured in this episode.`}
      </p>
      <div class="grid grid-cols-3 gap-4">
        <For
          each={episode.characters.slice(0, loadCount())}
          fallback={<p>Loading...</p>}
        >
          {(character) => <CharacterDetails characterUrl={character} />}
        </For>
        {counter() !== totalPage && (
          <>
            <button
              class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
              onClick={handleLoadMore}
            >
              Load More!
            </button>
          </>
        )}
      </div>
    </div>
  );
};
export default EpisodeBox;
```



In the code block above,  we created two signals for handling the different states:


- The first signal is to set the state of the number of characters to show at a particular time which in our case is six (6).
- The other is for getting and setting the total page for each episode.

We also created a function that loads more characters for each episode if we have yet to exceed that page's total number of characters. Next, we created two functions to check the episode and season number, which we then used in the return body.

In the return body, we mapped through the episode characters, got the URL for each character, and then passed it as props to the `CharacterDetails` component
If we head over to the browser, we should see the changes reflect as shown below:

![5](https://blog.openreplay.com/images/getting-started-with-solid-js/images/image05.png)




<h2>Session Replay for Developers</h2> 
<p><em>
Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data
</em></p>
<img alt="OpenReplay" width="768" height="400" src="https://blog.openreplay.com/assets/overview_Z17Qdyg.png" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em>






## Showing the character details

Navigate to the `src/components/CharacterDetails.jsx` and paste the code below into it:

```javascript
// src/components/CharacterDetails.jsx

import axios from "axios";
import { createSignal, onMount } from "solid-js";

const fetchCharacter = async (characterUrl) => axios.get(characterUrl);

const CharacterDetails = ({ characterUrl }) => {
  const [character, setCharacter] = createSignal();
  onMount(async () => {
    setCharacter((await fetchCharacter(characterUrl)).data);
  });
  return (
    <div class="flex rounded-lg flex-col border">
      <img
        class="rounded-lg"
        src={character()?.image}
        alt={character()?.name}
        loading="lazy"
      />
      <div class="p-4">
        <h2 class="text-center mt-2 text-2xl font-medium">
          {character()?.name}
        </h2>
        <p class=" mt-2 text-xl font-normal">{`From ${
          character()?.origin.name
        }, identifies as ${character()?.gender} of ${
          character()?.species
        } race`}</p>
        <p class=" mt-2 text-xl font-light">
          Current Status: {character()?.status}
        </p>
      </div>
    </div>
  );
};
export default CharacterDetails;
```

In the code block above, we destructured the character URL coming in and made a request to the API using the character URL. We passed the response to a created signal and then used the properties from the API's response in the return body.
The changes in the browser should be as shown below:



![6](https://blog.openreplay.com/images/getting-started-with-solid-js/images/image06.png)

## Adding infinite scrolling 

The episodes from the Rick and Morty movie API are many, and a good idea is to have a way to fetch more episodes. Some methods include pagination or infinite scrolling, but we will implement infinite scrolling in this application.

In the `App.jsx` file, copy the code below and paste it there:
```javascript
// imports and signal creation remain the same

const fetchNextData = async () => {
  if (episodes()?.info?.next) {
    const { data } = await fetchEpisodes(episodes()?.info.next);
    const modifiedEpisodes = [...episodes()?.results, ...data.results];
    setEpisodes((prevState) => ({
      ...prevState,
      results: modifiedEpisodes,
      info: data.info,
    }));
  }
};
const handleScroll = () => {
  if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
    fetchNextData();
  }
};

createEffect(() => {
  window.addEventListener("scroll", handleScroll);
});

// onMount method and the return body remain the same
```



We created a `fetchNextData` function that checks if there is a next option and fetches the following results. We destructured the data and passed it into the `episodes` signal. We also created a scrolling function that checks if we have scrolled toward the end of the document, and if yes, we call the `fetchNextData` function.

The next step is to add an event listener that listens to the scroll event and then calls the scrolling function. Our results should look like the GIF below:


![7](https://blog.openreplay.com/images/getting-started-with-solid-js/images/image07.gif)

[Here](https://res.cloudinary.com/dimagyjgo/image/upload/v1674573760/chrome-capture-2023-0-24_eos4nb.gif) is a link to the GIF on Cloudinary.

From the GIF above, we can see that the scroll bar reaches the end, and more episodes are fetched from the API.

## Conclusion

This article has looked at SolidJS and how to use SolidJS features to build applications with lots of reactivity. SolidJS also comes with a low learning curve, especially for developers coming from React. So have fun creating with Solid!!.

Readers can find the complete code for this tutorial [here](https://github.com/IsaacThaJunior/SolidJS-rick-and-morty).




[![newsletter](https://blog.openreplay.com/newsletter_Z1P0UIP.png)](https://newsletter.openreplay.com/)