Svelte 5 just got released and it’s packed with amazing new upgrades.
It’s like React now but leaner, easier, and yes — faster.
Just look at this:
❌ Before Svelte 5:
Creating state:
You could just create state variables with let
:
<script>
let count = 0;
let site = 'codingbeautydev.com'
</script>
✅ Now with Svelte 5…
useStat
e😱
<script>
let count = $state(0);
let site = $state('codingbeautydev.com');
</script>
vs React:
export function Component() {
const [count, setCount] = useState(0);
const [site, setSite] = useState('codingbeautydev.com');
// ...
}
But see how the Svelte version is still much less verbose — and no need for a component name.
Watching for changes in state?
In React this is useEffect
:
export function Component() {
const [count, setState] = useState(0);
useEffect(() => {
if (count > 9) {
alert('Double digits?!');
}
}, [count]);
const double = count * 2;
// ...
}
❌ Before Svelte 5:
You had to use a cryptic unnatural $:
syntax to watch for changes — and to create derived state too.
<script>
let count = $state(0);
$:() => {
if (count > 9) {
alert('Double digits?!');
}
};
$: double = count * 2;
</script>
✅ Now:
We have useEffect
in Svelte with $effect
👇
And a more straightforward way to create auto-updated derived state:
<script>
let count = $state(0);
$effect(() => {
if (count > 9) {
alert('Double digits?!');
}
});
const double = $derived(count * 2);
</script>
Svelte intelligently figures out dependencies to watch for, unlike React.
And what about handling events and updating the state?
In React:
export function Component() {
// 👇 `setState` function from `useState`
const [count, setCount] = useState(0);
return (
// event handlers are good old JS functions
<button
onClick={() => setCount((prev) => prev + 1)}>
Increase
</button>
);
}
❌ Before:
Svelte used to treat events specially and differently from props.
<script>
let count = $state(0);
</script>
Count: {count}
<br />
<!-- 👇 special on: directive for events -->
<button on:click={() => count++}>
Increase
</button>
✅ Now:
Svelte is now following React’s style of treating events just like properties.
<script>
let count = $state(0);
</script>
Count: {count}
<br />
<!-- 👇onclick is just a regular JS function now -->
<button onclick={() => count++}>
Increase
</button>
Custom component props
In React:
Props are a regular JS object the component receives:
// 👇 `props` is object
export function Person(props) {
const { firstName, lastName } = props;
return (
<h1>
{firstName} {lastName}
</h1>
);
}
❌ Before Svelte 5:
You had to use a weird export let
approach to expose component properties:
<script>
export let firstName;
export let lastName;
</script>
<h1>
{firstName}
{lastName}
</h1>
Now in Svelte 5:
There’s a $props
function that returns an object like in React!
<script>
const { firstName, lastName } = $props();
</script>
<h1>
{firstName}
{lastName}
</h1>
Custom component events
In React:
Events are just props so they just need to accept a callback and call it whenever:
import React, { useState } from 'react';
const Counter = ({ onIncrease }) => {
const [increase, setIncrease] = useState(0);
const handleIncrease = () => {
onIncrease(increase);
};
return (
<div>
Increase: {count}
<button onClick={handleIncrease}>Increase</button>
</div>
);
};
export default Counter;
❌ Before Svelte 5:
You’d have to use this complex createEventDispatcher
approach:
<script>
import { createEventDispatcher } from 'svelte';
let increase = $state(0);
const dispatchEvent = createEventDispatcher();
</script>
<button
on:click={() => {
dispatchEvent('increase', increase);
}}
>
Increase
</button>
✅ Now:
Events are now props like in React:
<script>
import { createEventDispatcher } from 'svelte';
let increase = $state(0);
const { onIncrease } = $props();
</script>
<button
onclick={() => onIncrease(count) }
>
Increase
</button>
Components: classes -> functions
Yes, Svelte has gone the way of React here too.
Remember when we still had to extend Component
and use render()
to create a class component?
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
incrementCount = () => {
this.setState((prevState) => ({
count: prevState.count + 1
}));
};
render() {
return (
<div>
<h1>Counter: {this.state.count}</h1>
<button onClick={this.incrementCount}>Increment</button>
</div>
);
}
}
export default Counter;
And then hooks came along to let us have much simpler function components?
Svelte has now done something similar, by making components classes instead of functions by default.
In practice this won’t change much of how you write Svelte code — we never created the classes directly anyway — but it does tweak the app mounting code a little:
import { mount } from 'svelte';
import App from './App.svelte'
// ❌ Before
const app = new App({ target: document.getElementById("app") });
// ✅ After
const app = mount(App, { target: document.getElementById("app") });
export default app;
Final thoughts
It’s great to see Svelte improve with inspiration from other frameworks.
Gaining the intuitiveness of the React-style design while staying lean and fast.
Web dev keeps moving.
Every Crazy Thing JavaScript Does
A captivating guide to the subtle caveats and lesser-known parts of JavaScript.