Svelte 5 is React on steroids😲

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:

HTML
<script> let count = 0; let site = 'codingbeautydev.com' </script>

βœ… Now with Svelte 5…

useState😱

HTML
<script> let count = $state(0); let site = $state('codingbeautydev.com'); </script>

vs React:

JavaScript
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:

JavaScript
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.

HTML
<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:

HTML
<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:

JavaScript
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.

HTML
<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.

HTML
<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:

JavaScript
// πŸ‘‡ `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:

HTML
<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!

HTML
<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:

JavaScript
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:

HTML
<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:

HTML
<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?

JavaScript
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:

JavaScript
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.