An intro to Svelte for ReactJS developers

An intro to Svelte for ReactJS developers - Coletiv Blog

While we mostly use ReactJS for our front-end web development here at Coletiv, we're always looking for ways to improve our code and our stack and, probably the most important point, our developer happiness. And that's exactly what I did during one of our Investment Times (for those who don't know what that is, the entire company basically gets the entire Friday afternoon to improve themselves for the greater good - aka, making Coletiv thrive!).

So, after playing around with Svelte and doing some projects, it seemed only fair to share my experience with it, how different it felt from ReactJS, and what a React developer can expect when getting into it.

What is Svelte?

For those who might be out of the loop, Svelte is a JavaScript framework that compiles your code when you build your app, which results in highly-optimized vanilla JavaScript. This means that you'll end up with smaller bundle sizes and with better performance. Svelte also sticks very close to raw HTML, CSS, and JavaScript (as we'll see further down). All of these reasons might as well just justify the fact that Svelte was voted the most loved web framework of 2021 (as seen on the StackOverflow 2021 Survey).

While this post will cover some of Svelte's major features, I invite you to do the Svelte tutorial as it will fully guide you through everything that the framework has to offer.

"Hello, World!", says Svelte

Let me first introduce you to the code before we dive into it.

<script>
  let name = "world";
</script>

<h1>Hello, {name}!</h1>

<style>
  h1 {
    color: #546659;
    font-size: 24px;
  }
</style>

Yeah, you're looking at it right. It looks like plain JavaScript, HTML, and CSS. How cool is that?

So, it seems that the Svelte convention is to have your <script> , then your html and finally your <style> tag. On your <script> you'll have most of your logic and state (as expected) and your <style> will deal with any CSS that you might need (and the coolest part of this is that these styles are scoped to the component). And it's just built-in! For this to work on ReactJS we would probably need to use css-modules or styled components.

Now, the html might look like regular HTML but it's not. There are specific features regarding Svelte like if statements (that look like {#if}) and map() (that looks like {#each} ). Personally, I've grown tired of React's conditional rendering since it just blends too well with the rest of the code so seeing how Svelte deals with that was really interesting. Here's an example showing the same code on React and on Svelte:

// React
{ isDarkMode
    ? <h1>Dark Mode Zone</h1>
    : <h1>Light Mode Zone</h1>
}

// Svelte
{#if isDarkMode}
  <h1>Dark Mode Zone</h1>
{:else}
  <h1>Light Mode Zone</h1>
{/if}

While the React code looks more compact, I personally feel like our conditions end up extremely messy when we have a lot of logic on them (like several conditions and then nested ones) and the simplicity of Svelte here somewhat baffled me. While it does increase the number of lines, I'm now fully aware of what I'm doing and where the if/else starts and ends.

I hope that this short intro to Svelte's structure was enough to entice you (remember, there's always Svelte's tutorial to dive deeper) because we're jumping to...

State Management

In 2018 we were introduced to Hooks on React and it completely revolutionized the way we do code. However, sometimes, we end up battling with our own useState and its updates and I'm fairly sure that everybody working with React got their fair share of headaches with it (let's throw useEffect and useMemo into the mix while we're at it 😬).

Svelte deals with our state in a simpler way. Our useState from React is a simple variable assignment on Svelte. Here's a comparison:

// React
import { useState } from 'react'

export default const Counter = () => {
	const [count, setCount] = useState(0);

	return (
		<>
			<h1>Count at: {count}</h1>
			<button onClick={() => setCount(count++)}>Increase</button>
			<button onClick={() => setCount(count--)}>Decrease</button>
		</>
	)
}

// Svelte
<script>
	let count = 0;
</script>

<h1>Count at: {count}</h1>
<button on:click={() => count++}>Increase</button>
<button on:click={() => count--}>Decrease</button>

Svelte will simply update your code! πŸͺ„

But what about complex state management?

On React we have several options to deal with state that is controlled/listen to on different components (like Redux, useContext and useReducer) and they are great at what they do.

Svelte has two approaches to its state.

Context API

For simpler states, Svelte has its Context API, which makes the state available to the component and its descendants; this basically means that you don't have to prop drill from a Parent to several Grand-grand-children and instead you can use Context. Context API has two built-in functions - getContext and setContext. As the names clearly say, getContext will retrieve the values, and setContext sets the values. With this, we have a great way of managing the state for components within the same component tree.

Stores

There are times where local state and component-tree state just can't do the job and Svelte has Stores to deal with it. Stores are objects that have a special method called subscribe that allows components to be notified when one of the values of these objects changes. Svelte has two types of stores: writable ones and readable ones.

Writable Stores

Writable stores create objects with values that can be set from components subscribed to them. It is accompanied by two methods: set and update. set will overwrite the value set on the store while update will receive a callback function as an argument and will take the existing value on the store as its argument and, well, update it. The following code shows the application of set and update with two files, store.js , and App.svelte (the code can also be found, and played with, here).

// store.js
import { writable } from 'svelte/store';

let counter = writable(1);

export { counter };

// App.svelte
<script>
	import { counter } from './store.js'

	function incrementCounter() {
	  counter.update(n => n + 1);
	}

	function setCounter() {
		counter.set(2)
	}
</script>

<h1>{$counter}</h1>
<button on:click={incrementCounter}>Increment Counter</button>
<button on:click={setCounter}>Set counter as 2</button>

Notice the dollar sign, $, used when calling counter. That's how you can access values of your store!

Readable Stores

Like writable stores, readable stores also have objects in them. While they can not be updated by external components, they can be updated within the store This means that readable stores are great to deal with immutable data that you still need to access from several different spots on your app! You work with them by creating your store using the readable method and then you access them using $ like seen on the example above (here's the live example).

// store.js
import { readable } from 'svelte/store'

let startingSeconds = 0;

export const seconds = readable(startingSeconds, set => {
	setInterval(() => {
		set(startingSeconds++)
	}, 1000)
})

// App.svelte
<script>
	import { seconds } from './store'
</script>

<h1>{$seconds} have passed</h1>

And that's it

These are, for me, the starting bricks of Svelte but there's so much more to it, like SvelteKit, (and quirky things like two-way data binding) and, honestly, the more I play with Svelte the more I get marveled by how easy it is to work with it and get something up-and-running. I'm surely going to keep using it!

What did you think about it? Did this post spike your interest? Will you give Svelte a try? Let us know on our Twitter or in the comments section below! 😎

Thank you for reading!

Thank you so much for reading, it means a lot to us! Don’t forget to follow Coletiv on Facebook, Twitter, and LinkedIn as we keep posting interesting articles on technologies, processes, and experiences.


If you'd like to work with us on a digital product just drop us a message here.




Do you want to become part of our community?

Join our newsletter 😎