- Published on
React vs Svelte: Musings on the Diverging Philosophies of Both Frameworks
- Authors
- Name
- Hussain Fazaal
- @fazofazaal
In this article, we will examine the contrasting philosophies and strengths of both React and Svelte, focusing on a side project that leverages the unique advantages of each. The public-facing app is built with Svelte for its low bundle size and fast runtime speed, while the back-office admin dashboard app is constructed with React due to familiarity, library availability, and suitability for large codebases.
The Quick Learning Curve of Svelte
Svelte's straightforward syntax and minimal boilerplate make it easy for developers to pick up and start building applications quickly. Its simplicity helps reduce the learning curve when compared to React, which has a steeper learning curve due to its use of JSX mixed with ES6 Javascript features as well as the uni-directional data flow based on the Flux architecture.
Prop Drilling in Svelte
One of Svelte's features that stands out is the ease of prop drilling. Instead of passing parent props down through multiple levels of components like in React, Svelte allows developers to pass props directly by using the prop name (e.g., {user}
). This approach reduces verbosity and improves code readability.
// Parent.svelte
<script>
import Child from './Child.svelte'
let user = { name: 'John', age: 30 }
</script>
<Child {user} />
// Child.svelte
<script>
export let user
</script>
<p>{user.name} is {user.age} years old.</p>
Built-in Animate Directive
Svelte's built-in animate directive enables developers to create smooth animations and page transitions without relying on third-party libraries. This feature further showcases Svelte's commitment to a lightweight and performant framework.
<script>
import { flip } from 'svelte/animate';
let items = [1, 2, 3, 4, 5];
</script>
{#each items as item (item)}
<div animate:flip>{item}</div>
{/each}
The Magic of Svelte
Svelte's compiler magic can sometimes feel a bit overwhelming, as standard JavaScript declarations work as reactive state declarations. While this may be confusing at first, it showcases the power of Svelte as both a UI language and a framework.
<script>
// This is a reactive state declaration that assumes a regular JavaScript variable declaration.
// The compiler will automatically update the value of count when the value of count changes.
// This has been called "magic" by Svelte detractors as it can be confusing to newcomers.
let count = 0;
function increment() {
count += 1;
}
</script>
<button on:click={increment}>
Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
React's Functional Programming Paradigm
Despite Svelte's advantages, React's functional programming paradigm remains appealing to many developers. The functional approach, combined with hooks, provides a robust foundation for building highly reactive user interfaces. React's extensive ecosystem of libraries and its widespread adoption make it a reliable choice for complex projects.
import React, { useState } from 'react'
function Counter() {
const [count, setCount] = useState(0)
const increment = () => {
setCount(count + 1)
}
return (
<button onClick={increment}>
Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
)
}
Svelte's Stores and Derived Stores vs React's Context API
Another advantage of Svelte is its Stores and Derived Stores, which provide a straightforward and enjoyable way to manage state across components. With Svelte's stores, you can easily create, update, and subscribe to values, making state management a breeze. Derived stores allow for the creation of computed values based on other stores, enabling developers to keep their state in sync effortlessly.
// store.js
import { writable, derived } from 'svelte/store'
export const count = writable(0)
export const doubleCount = derived(count, ($count) => $count * 2)
// App.svelte
<script>
import { count, doubleCount } from './store';
function increment() {
$count += 1;
}
</script>
<button on:click={increment}>Increment count</button>
<p>Count: {$count}</p>
<p>Double count: {$doubleCount}</p>
In contrast, React's native Context API, while powerful, can sometimes feel more cumbersome and less intuitive. To utilize Context, developers must create context providers, consumers, and manage updates through the use of hooks like useContext and useReducer. This process can lead to more boilerplate code and less readability compared to Svelte's stores.
// CountContext.js
import { createContext, useContext, useReducer } from 'react'
const CountContext = createContext()
export const useCount = () => {
const context = useContext(CountContext)
if (!context) {
throw new Error('useCount must be used within a CountProvider')
}
return context
}
const countReducer = (state, action) => {
switch (action.type) {
case 'increment':
return state + 1
default:
throw new Error(`Unhandled action type: ${action.type}`)
}
}
export const CountProvider = ({ children }) => {
const [count, dispatch] = useReducer(countReducer, 0)
return <CountContext.Provider value={{ count, dispatch }}>{children}</CountContext.Provider>
}
// App.js
import React from 'react'
import { CountProvider, useCount } from './CountContext'
function Counter() {
const { count, dispatch } = useCount()
const increment = () => {
dispatch({ type: 'increment' })
}
return (
<>
<button onClick={increment}>Increment count</button>
<p>Count: {count}</p>
</>
)
}
function App() {
return (
<CountProvider>
<Counter />
</CountProvider>
)
}
export default App
In summary, Svelte's Stores and Derived Stores offer a more streamlined and enjoyable experience for state management, while React's Context API, though powerful, can be more challenging to work with. This further highlights the differing philosophies between the two frameworks, with Svelte focusing on simplicity and ease of use, and React emphasizing flexibility and extensibility.
Conclusion: Finding the Right Fit
Ultimately, both React and Svelte have their merits and use cases. While Svelte is an excellent choice for lightweight applications with a focus on performance and simplicity, React shines when it comes to large codebases and an extensive ecosystem. As developers, it's essential to choose the right tool for the task at hand and appreciate the unique philosophies and strengths each framework offers.