Modern web development offers a plethora of frameworks and libraries to choose from, each with its own strengths and weaknesses. Among these, React and Svelte have emerged as two popular options. In this article, we’ll explore the core concepts, differences, and practical examples of both React and Svelte, helping you decide which one suits your needs best.
React: The Established Giant š
React, developed by Facebook, is a JavaScript library for building user interfaces, primarily for single-page applications. It allows developers to create large web applications that can update and render efficiently in response to data changes. React’s core concept revolves around components, which are reusable pieces of code that manage their own state and structure.
Svelte: The New Kid on the Block š
Svelte, on the other hand, is a relatively new framework developed by Rich Harris. Unlike traditional frameworks like React, Svelte shifts much of the work to compile time, producing highly optimized vanilla JavaScript at build time. This approach can lead to faster runtime performance and smaller bundle sizes.
Core Concepts
React: Component-Based Architecture š§©
React is built around components. Each component represents a part of the UI and can maintain its own state and lifecycle. Hereās a simple example of a React component:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default Counter;
In this example, we define a āCounterā component that uses the āuseStateā hook to manage its state. The ācountā state is displayed in a paragraph, and a button allows users to increment the count.
Svelte: Compiled Magic āØ
Svelte takes a different approach. Instead of using a virtual DOM like React, Svelte shifts much of the work to compile time, generating highly optimized vanilla JavaScript code. Hereās a similar counter example in Svelte:
<script>
let count = 0;
</script>
<main>
<p>You clicked {count} times</p>
<button on:click={() => count += 1}>
Click me
</button>
</main>
In Svelte, the component is written in a single file with three sections: ā<script>, <style>ā, and the markup. The reactive assignments make the code simpler and more intuitive.
Key Differences
Performance š
One of Svelteās main selling points is its performance. Since Svelte compiles your code to optimized vanilla JavaScript at build time, there is no virtual DOM overhead. This often results in faster runtime performance and smaller bundle sizes.
React, while highly optimized, still relies on a virtual DOM. This can add some overhead, although modern React applications can be highly performant with proper optimization.
Learning Curve š
React has a steeper learning curve compared to Svelte. React’s ecosystem is vast, and understanding concepts like hooks, context, and the virtual DOM can take some time.
Svelte is designed to be more approachable. Its syntax is closer to plain HTML, CSS, and JavaScript, making it easier for beginners to pick up and start building.
Ecosystem and Community š
React boasts a massive ecosystem and a large, active community. There are countless libraries, tools, and resources available for React developers. This makes it easier to find solutions to problems and integrate with other technologies.
Svelteās ecosystem is growing but is not as extensive as Reactās. However, the community is passionate and supportive, and the framework is quickly gaining traction.
Practical Examples
Todo List Application
Letās build a simple Todo List application in both React and Svelte to see how they compare in a real-world scenario.
React Todo List
First, weāll create a new React project using Create React App:
npx create-react-app react-todo
cd react-todo
npm start
Next, letās create a āTodoā component and a āTodoListācomponent:
// src/components/Todo.js
import React from 'react';
function Todo({ todo, toggleTodo }) {
return (
<li
onClick={() => toggleTodo(todo.id)}
style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
>
{todo.text}
</li>
);
}
export default Todo;
// src/components/TodoList.js
import React, { useState } from 'react';
import Todo from './Todo';
function TodoList() {
const [todos, setTodos] = useState([]);
const [newTodo, setNewTodo] = useState('');
const addTodo = () => {
setTodos([...todos, { id: Date.now(), text: newTodo, completed: false }]);
setNewTodo('');
};
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
));
};
return (
<div>
<input
type="text"
value={newTodo}
onChange={(e) => setNewTodo(e.target.value)}
/>
<button onClick={addTodo}>Add Todo</button>
<ul>
{todos.map(todo => (
<Todo key={todo.id} todo={todo} toggleTodo={toggleTodo} />
))}
</ul>
</div>
);
}
export default TodoList;
We import and use the āTodoListā component in the āAppā component:
// src/App.js
import React from 'react';
import TodoList from './components/TodoList';
function App() {
return (
<div className="App">
<h1>React Todo List</h1>
<TodoList />
</div>
);
}
export default App;
Svelte Todo List
First, weāll create a new Svelte project using Svelteās template:
npx degit sveltejs/template svelte-todo
cd svelte-todo
npm install
npm run dev
Next, letās create a āTodo.svelteā component and a āTodoList.svelteā component:
<!-- src/components/Todo.svelte -->
<script>
export let todo;
export let toggleTodo;
</script>
<li
on:click={() => toggleTodo(todo.id)}
style:text-decoration={todo.completed ? 'line-through' : 'none'}
>
{todo.text}
</li>
<!-- src/components/TodoList.svelte -->
<script>
import { onMount } from 'svelte';
import Todo from './Todo.svelte';
let todos = [];
let newTodo = '';
const addTodo = () => {
todos = [...todos, { id: Date.now(), text: newTodo, completed: false }];
newTodo = '';
};
const toggleTodo = (id) => {
todos = todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
);
};
</script>
<main>
<input
type="text"
bind:value={newTodo}
/>
<button on:click={addTodo}>Add Todo</button>
<ul>
{#each todos as todo (todo.id)}
<Todo {todo} {toggleTodo} />
{/each}
</ul>
</main>
We import and use the āTodoListā component in the āApp.svelteā component:
<!-- src/App.svelte -->
<script>
import TodoList from './components/TodoList.svelte';
</script>
<main>
<h1>Svelte Todo List</h1>
<TodoList />
</main>
Comparison
In both React and Svelte, we created a Todo List application with similar functionality. However, there are notable differences in the development experience:
- Code Structure: Svelteās single-file component structure is more compact and intuitive. Reactās separation of concerns (JavaScript, HTML, CSS) into different files can be beneficial for larger applications but may add complexity for simpler ones.
- State Management: Reactās āuseStateā hook is powerful and flexible, but Svelteās reactive assignments (let count = 0; count += 1;) provide a more straightforward way to manage state.
- Event Handling: Svelteās event handling (on:click) feels more natural and is less verbose compared to Reactās (onClick).
Advanced Topics
React: Context API and Redux šļø
For more complex state management, React offers the Context API and integration with libraries like Redux. The Context API allows you to share state across the component tree without prop drilling:
import React, { createContext, useContext, useState } from 'react';
const ThemeContext = createContext();
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
function ThemedButton() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Switch to {theme === 'light' ? 'dark' : 'light'} theme
</button>
);
}
function App() {
return (
<ThemeProvider>
<ThemedButton />
</ThemeProvider>
);
}
export default App;
Svelte: Stores and Custom Stores šŖ
Svelteās approach to state management includes writable stores, which allow you to create and share reactive state:
<!-- src/stores.js -->
import { writable } from 'svelte/store';
export const count = writable(0);
<!-- src/App.svelte -->
<script>
import { count } from './stores.js';
$: console.log($count);
</script>
<main>
<button on:click={() => $count += 1}>
Count: {$count}
</button>
</main>
Svelte also supports custom stores for more complex state management:
<!-- src/customStore.js -->
import { writable } from 'svelte/store';
function createCount() {
const { subscribe, set, update } = writable(0);
return {
subscribe,
increment: () => update(n => n + 1),
decrement: () => update(n => n - 1),
reset: () => set(0)
};
}
export const count = createCount();
<!-- src/App.svelte -->
<script>
import { count } from './customStore.js';
</script>
<main>
<button on:click={count.increment}>
Increment
</button>
<button on:click={count.decrement}>
Decrement
</button>
<button on:click={count.reset}>
Reset
</button>
<p>Count: {$count}</p>
</main>
Conclusion
Choosing between React and Svelte depends on your project requirements and personal preferences. Reactās mature ecosystem and extensive resources make it a solid choice for large-scale applications, while Svelteās simplicity and performance optimizations are ideal for smaller projects or developers looking for an easy-to-learn framework.
Both frameworks have their strengths and are continuously evolving, making web development more efficient and enjoyable. Whether you prefer the established giant or the new kid on the block, youāll find robust tools and vibrant communities ready to support your journey in modern web development. Happy coding! š