SolidJS Library - a practical guide to building simple and performant user interfaces

SHARE

SolidJS Library - a practical guide to building simple and performant user interfaces

SHARE

- 16 min to read

SolidJS Library - a practical guide to building simple and performant user interfaces

Build a fast website with SolidJS! This practical guide covers setup, styling, state management, data fetching, and more. By building a movie app, you'll learn how to use SolidJS and optimize your projects for speed and efficiency.

By Chidera Chukwuka

SolidJS Library - a practical guide to building simple and performant user interfaces

In this practical guide to SolidJS, you will learn about SolidJS, its setup procedure, and file organization. You will discover how to add components, style, and manage state in a SolidJS app. Furthermore, you will explore how to fetch data from a server, pass data between components and navigate between pages.

You will build a simple movie app that displays lists of movies that allows searching and viewing details. You will utilize Open Movie Database (OMDb) API to get the movie data.

By the end of this article, You'll have an in-depth knowledge of how SolidJS functions and how to use it in rapidly developing effective and fast websites.

  • Introduction to SolidJS
  • How to set up a SolidJS project
  • Project Structure
  • Solid Components
  • Styling in SolidJS
  • State management
  • Fetching data
  • Control flow
  • Passing data between components
  • Routing and Navigation
  • Handling events
  • Optimization best practices
  • Building and deploying Solid projects
  • Conclusion

Introduction to SolidJS

SolidJS is a modern declarative JavaScript library for UI component development. It offers a high-performance option for developing dynamic user interfaces because of its simple, effective, and quick design. Because SolidJS uses the reactive programming paradigm, components dynamically update in reaction to changes in their dependencies without the need for explicit data binding or labor-intensive DOM manipulation.

SolidJS's fine-grained reactivity mechanism is one of its standout characteristics. It ensures that the UI always represents the most current state of the application by updating the impacted components immediately whenever a dependent changes. By only updating the UI elements that are affected by changes, this reactive approach is much more efficient than other libraries and frameworks at updating the user interface.

SolidJS has a component-based design where UI components get packaged into independent functional units. Its components are flexible and adaptable since they may contain local state, props, and lifecycle methods. As the components are easily reusable across many sections of an app, it encourages code reuse and maintainability. These components may be constructed using declarative template-based syntax, which makes it simple to design UI elements using familiar HTML-like syntax and combine them with JavaScript logic to manage dynamic behavior.

SolidJS's capacity for modification and extension is another asset. SolidJS's robust and adaptable API makes it possible to customize and integrate it with other frameworks and packages. This library may be adapted to various project needs and development workflows thanks to its support for integration with already-existing tools and technologies. Because of this, SolidJS is a very flexible option for developing modern user interfaces in JavaScript.

SolidJS supports modern framework features such as:

  • JSX
  • Fragments
  • Context
  • Portals
  • Suspense
  • Streaming SSR
  • Progressive hydration

It uses Vite as the principal building tool that conveniently packs your application's JavaScript.

How to set up a SolidJS project

You'll use a Vite template which has the necessary boilerplate code to create a SolidJS project.

Run the npx degit command to clone the template from the repository solid/js/templates/js to your project folder in a new terminal window:

Replace solid-movie with the relevant name for your application.

If you prefer to use TypeScript, run the following command instead:

The /js template and /ts template both produce the same results.

When the template has been cloned to your project folder, go to that directory and install the project's required dependencies:

Use the following command to launch the development server after the dependencies are successfully installed:

To access the SolidJS launch page, open your browser at http://localhost:3000/.

Project structure

Here is a sample file structure for a SolidJS application:

  • src: you will place your application's source code in this directory. It might have subdirectories to arrange your resources, assets, and other pieces.
  • assets: static files used by the application, such as images, fonts, and other resources, can be placed in this directory. The assets can be arranged according to the type or function in the application.
  • App.js: the bootstrapping of the components and any global configurations or providers are done in this file, which also serves as the SolidJS application's entry point.
  • Index.js: this file is in charge of rendering the primary SolidJS application component, App.js, into the HTML document and attaching it to the DOM.
  • vite.config.js: it is a configuration file used by Vite, the default build tool suggested for usage with SolidJS.

This gives a general understanding of the SolidJS file structure. Although the precise file structures may vary based on the size and complexity of your application, you can arrange your files in a way that makes sense for your particular use case.

Solid components

In a SolidJS application, components serve as the basic building blocks and encapsulate the UI logic and state for individual sections. Components are defined as reactive functions, which update dynamically as their dependencies change, following the reactive programming paradigm.

Components in SolidJS are described as functions that return a UI template. These functions return JSX or plain HTML and accept reactive state and props as inputs. Functional components are reusable and maintainable due to their simplicity and ease of reasoning.

In the src directory, create a components folder that will house the necessary components for the app. Next, create three files for the components Movie-Card.jsx, Movie-List.jsx, and Movie-Details.

Write the following code in the Movie-Card.jsx file:

This code snippet defines the functional component MovieCard. It returns a div element with an image, a title, the year, and a "See details" button. The MovieCard component is exported at the end of the code so it can be imported and used in different parts of the application.

Now, in the Movie-List.jsx file:

The MovieList component is created. The component displays a movie card after importing the MovieCard component from "./Movie-Card". The title is shown in an h1 element inside the MovieList component using a header element.

It is possible to return several elements from a component without needing to wrap them in a container element by using the shorthand syntax of Fragments (<></>). Then the component is exported at the end of the code.

Finally, the Movie-Details.jsx file:

The MovieCard component is built with just one div. It is exported, making it accessible across the app. Now import the components into the root component App.jsx:

You import the MovieList and MovieDetails components from their respective files.

Styling in SolidJS

Making interactive and aesthetically pleasing web applications requires styling.

These are just a few of the styling methods offered by SolidJS:

  • Inline styling
  • CSS classes
  • CSS-in-JS libraries
  • CSS modules
  • CSS libraries
  • Dynamic style utilizing reactive variables

These methods for styling in SolidJS enable you to design well-structured, modular, and dynamic user interfaces.

In this application, you will make use of Solid-bootstrap in order to speed up the development process. Solid Bootstrap is a library of pre-made UI elements for Solid applications built on the Bootstrap framework. The components and style possibilities offered by Solid-Bootstrap are numerous.

To use it in your Solid project, execute the subsequent command to install solid-bootstrap using npm or yarn:

Solid Bootstrap offers pre-built CSS files that you may use to customize your application.

Add the CSS file to your index.html file:

Now your SolidJS components can import and utilize the solid-bootstrap elements.

Proceed to style your components using solid-bootstrap elements.

Update the MovieCard.jsx file:

The components for the button and card are imported from solid-bootstrap. An image is displayed using the Card.Img element, and the variant="top" parameter specifies that the picture should appear at the top of the card. A Card.Title and a Card.Text elements are found in the "Card.Body" element and are used to display the movie's title and its release year, respectively. A button is displayed last, and the variant="primary" prop specifies that the button should be blue.

Now update the MovieList component:

The Col, Form, Spinner, and Row elements from the solid-bootstrap library are imported. There is a search input field and a section has a row of movie cards that are individually presented using the "Col" component in a column.

Then the MovieDetails.jsx component:

An h1 tag can be found in the component's return statement. It also has two Card components, the first of which has two Card.Text components and a Card.Img component for the display of the movie's plot and its year of release. The director, stars, and rating of the film are displayed using three Card.Text components found in the second Card component.

State management

State management is a vital component of developing contemporary web applications, and SolidJS provides a variety of methods for doing so effectively. The reactive state, which enables developers to create and manipulate application states reactively, is the basic idea behind SolidJS's state management system. With a reactive state, there is no need for manual DOM modification because the user interface is updated immediately anytime the underlying state changes.

SolidJS offers robust capabilities for managing states reactively and effectively, whether it be component-level state, props, context, or global state management via the store API.

The state is commonly managed in SolidJS using Signals, which generates a reactive state value and a setter function that may be used to update the value. Solid's reactivity is built on Signals. They include dynamic values - when you modify a signal's value, everything that relies on it is updated immediately. The initial value is the parameter used to construct the Signal, and the return values are an array with two functions a getter and a setter. The first returned value is not the value itself, but rather a getter, a function that returns the current value.

Let's import createSignal from solid-js to create a signal and use it in the MovieList component:

Utilizing the createSignal function from SolidJS defines three signals:

  • movies: an empty array that will be used to store the list of movies that was fetched from an external API.
  • searchWord: a string that has the value "men" as its starting value and represents the user's current search query.
  • loading: a boolean that, by default, is initialized to false and determines whether the component is presently loading data.

The value of the search input field is currently set using searchWord(). Depending on whether the loading signal is true, the movie list section conditionally displays a spinner.

Fetching data

In a SolidJS application, fetching data entails sending asynchronous queries to a remote API or server, that are subsequently used to update the user interface (UI). You will use either built-in browser APIs like fetch or third-party libraries like Axios since SolidJS lacks built-in data fetching functionality. It's crucial to adhere to best practices for handling errors, handling retries, and controlling the lifecycle of the fetch operation while retrieving data in a SolidJS application.

In the MovieList component, you will use the fetch API to retrieve movies from OMDb. To receive an API key that will be required while making API requests, you must register on the website.

Create a ".env" file at the root of your app to keep this API key as an environment variable. The environment variables stored in the .env file are loaded by Vite by use of dotenv. Add the values in a variable in the .env file like follows:

The function that will make the API calls will be created in a createEffect function.

Effects are intended for side effects that read the reactive system but do not write to it. Effects are common ways to make code segments run whenever dependencies change, such as when manually altering the DOM or making API calls.

createEffect provides a new calculation that runs the supplied function in a tracking scope while continuously tracking its dependencies and rerunning the function whenever the dependencies change.

Updating the MovieList.jsx component:

First, import the createEffect to use it. Environment variables declared in .env files at build time are used to define the apiKey constant. It guarantees that the API key is kept private and hidden from view in the client-side code.

The effect gets triggered when the component renders and runs the asynchronous function getMovies(). Following that, a GET request is sent with the search criteria and API key supplied to the OMDB API. The res.json() method is used to parse the response data, and the output is converted into a JavaScript object. The setMovies() function stores the search array in the component's state. In order to signal that the process is complete, setLoading(false) is called at the end.

Control flow

Control flow is a crucial idea in programming that enables programmers to execute code only when specific conditions are met or to carry out repetitive activities. Reactive programming techniques and specific directives for conditional rendering and iteration are used in SolidJS to accomplish control flow. These capabilities offer a powerful and adaptable method for handling conditional logic and dynamic rendering in SolidJS applications.

The for directive in SolidJS allows you to iterate over arrays or other iterable data and dynamically render items for each entry in the array.

To use the for directive, you have to import it first in the MovieList.jsx component:

The code determines whether movies() is truthy (not null, undefined, or empty) and checks whether the length of the movies() array is greater than zero. If both requirements are satisfied, it renders a Row component with a loop using the For directive from SolidJS.

It renders a MovieCard component wrapped in a Col component with given column widths for various screen sizes (sm: 12 columns for small screens, md: 3 columns for medium screens) for each movie object in the movies() array. Employing conditional rendering, a p tag is used to display a message if the movies array is empty.

Passing data between components

Props are used to facilitate data flow between components. Props are values or objects that are sent from a parent component to a child component. They can be defined in a child component and used to access data coming from the parent component.

In the MoiveList component, you will pass a movie item as a prop to the MovieCard component:

For efficient rendering in SolidJS, the key prop is set to movie.imdbID to provide a distinct identity for each MovieCard component in the loop.

Then proceed to the MovieCard component to receive the prop and utilize it.

This component receives a prop named movie, which is an object that includes information about a movie, such as a title, year, and poster.

The component then utilizes object destructuring to extract these properties and use them in the Bootstrap Card component.

This is what your app will look like:

Routing and navigation

SolidJS uses Solid Router to implement routing and navigation. Solid Router is a multipurpose router for SolidJS. Iit functions whether rendering is on the client or the server. It draws on and integrates the React Router and Ember Router principles. Route definitions can be made explicitly in the JSX template for your app, but you can also pass your route information as an object. It allows hierarchical routing, allowing navigation to modify only a portion of a component rather than entirely replacing it. You can utilize it with suspense, resources, and lazy components because it supports all of Solid's SSR methods and has Solid's transitions built in.

Installing a solid-router is required in order to use it. It may be installed using a package manager like npm or yarn.

Now you can proceed to set up the application's routes.

Open the src/index.jsx file, import and wrap your root component within the Router component:

The Router gives you a context that enables you to display the routes throughout the app. Now, open the src/App.jsx file to configure app routes:

First, The Routes and Route components from the @solidjs/router library are imported.

This code leverages the Solid Bootstrap Container component to enclose and add padding to the application's content. A navigation bar is made using the Navbar component from the same package. The Routes component defines the routes, while the Route component specifies the path and the associated component to render. To make sure that the navigation is handled by the router, @solidjs/router supplies the A component that should be used in place of the standard anchor tag.

The root path / is the first route specified, and it renders the MovieList component. The /movie-details/:id path, which is the second declared route, renders the MovieDetails component. The colon (:) in the path denotes that a dynamic parameter (the movie id) will be passed.

You have to set up the "See details" button to navigate to the MovieDetails page.

The link to the movie details page is made using an A component from the router library with the href property pointing to /movie-details/imdbID.

Then finishing up on the MovieDetails.jsx:

The component imports the Badge, Card, and Spinner components from Solid Bootstrap as well as the createSignal and createEffect utilities from the SolidJS library. Additionally, the useParams method from the @solidjs/router package is imported to take the id parameter out of the URL. useParams obtains a reactive, store-like object that contains the Route's current route path parameters.

The component specifies the movieDetail and loading signals. loading is a boolean that is set to true while the API request is being made and set to false when the request is finished. movieDetail stores an object containing the details of the movie that were fetched from the API.

When the component gets rendered, the effect specified by the component is executed. The effect sends an asynchronous request to the OMDb API to retrieve the movie information associated with the URL's extracted id parameter. The loading signal is set to false and the movieDetail signal is updated with the response data when the API response is received.

While the API request is being processed, the component displays a loading spinner. Once the API response has been received, the component displays the movie details.

The movie-details page now looks like this:

Handling events

In a SolidJS project, handling events involves capturing user interactions like button clicks, form submissions, and keyboard events and reacting to them with the required logic. SolidJS offers event bindings that capture several types of events, including onClick, onChange, onSubmit, and others, which may be incorporated as attributes on JSX elements. With the aid of these event bindings, you can affix event handlers to specific elements.

Update the MovieList.jsx:

The handleSearch function serves as an event handler for the search input field's onChange event, which modifies the searchWord signal to reflect the most recent value that the user has entered. When the function is being executed, the effect automatically subscribes to any signals that are read and reruns whenever any of them change.

Optimization best practices

SolidJS is created to be performant and versatile. It includes a variety of optimization approaches to aid in enhancing your application's speed and effectiveness. Here are some best recommendations for improving SolidJS applications:

  • Utilize dynamic imports - SolidJS enables dynamic imports, which helps speed up your application's initial load time. Instead of loading everything at once, you may use the lazy function to just load components or modules as needed.
  • Avoid excessive renders - one of the main advantages of SolidJS is its capacity to re-render the UI components that have changed. The timing and frequency of your re-renders must be considered, though. If any resources or subscriptions need to be cleaned up once a component is unmounted or modified, use the onCleanup lifecycle method.
  • Utilize memoization - memoization is a performance-enhancing method that involves caching the outcomes of intensive function calls. The createMemo method in SolidJS can be used to store a function's output in a memo. It can lower the number of pointless re-renders and boost your application's overall performance.
  • Employ the key property - the ability of SolidJS to effectively update the DOM depends on the ability to uniquely identify elements in a list using the key property. It's crucial to avoid using the index as the key and use a reliable, distinct key for each element.
  • To enhance rendering, use defer and async- until the subsequent render cycle, a function's execution can be postponed using SolidJS' defer function. To run a function asynchronously, you can employ the async function.


Developers may optimize SolidJS applications to deliver a quick and effective user experience by adhering to these best practices.

Building and deploying Solid projects

SolidJS projects require several processes to build and deploy, including code bundling and compilation as well as optimization, deployment, and monitoring. All these processes are handled by Vite, a tool for building and deploying SolidJS apps. It is an effective tool that can assist developers in streamlining their development processes and creating high-performance SolidJS applications for use in real-world scenarios. With features like hot module replacement, improved production builds, and quick development server startup times, it is a fast and lightweight tool that provides a modern development experience.

When you're prepared to build the application for usage in production, execute the following command:

It will start Vite's build process, which bundles the application code into optimal files prepared for production deployment. The dist directory will be the default location for the stored files.

You can deploy the newly generated files to a hosting platform or production server once the build procedure is complete. It can entail deploying to a Platform as a Service (PaaS), employing a cloud-based hosting provider, or uploading the files to a web server.

After deploying the files, you can serve them using a web server or hosting provider of your choice. The server can be set up to serve the SolidJS application's entry point, the index.html file, and any additional static files generated during the building process.

The meta framework for SolidJS

It is also worth noting that SolidJS has a meta framework, SolidStart, which makes building web applications faster. SolidStart is a feature-rich and flexible framework for creating cutting-edge web apps using SolidJS. Developers looking to develop complex applications fast and effectively without sacrificing maintainability or scalability will find its feature set quite extensive and its API user-friendly. SolidStart helps build web applications in Solid.

Conclusion

In conclusion, SolidJS is a powerful and effective library that empowers programmers to create efficient and user-friendly web applications. You have covered every crucial SolidJS topic in this practical guide, from project setup through component creation, styling, and state management. Moreover, you have examined how to handle events, convey data between components, fetch data from a remote server, and best practices for optimization.

You will learn SolidJS' versatility and power as you continue to explore it and develop more complicated web applications. SolidJS is a valuable addition to your toolkit for web development projects due to its rising popularity and strong community support.

Github repo for the project: https://github.com/bejamas/solid-movie.

Share

Written by

Chidera Chukwuka Writing Program Member

An ardent and internally propelled developer proficient in blending the art of design with the skill of programming to deliver a top-notch and immersive user experience. I have 4+ years of sophisticated experience working with organizations in the software and engineering sector as a Frontend Engineer. I am keen on the aesthetics, usability, and accessibility of applications.

Readers also enjoyed