Once Upon a Time, Chaos Reigned in Front-End Development
The front-end world has been ruled by frameworks that promised you freedom:
- React, the "build anything, but at what cost?" framework.
- Vue, the "everything is kinda okay but just try to reuse your logic, I dare you" framework.
- Svelte, the "we’re simple until you need inheritance, then good luck" framework.
For years, developers convinced themselves these tools were the pinnacle of modern engineering. But behind the promises of "flexibility" and "developer experience" lurked frustration, duplication, and tears.
The Challenge: A Button with a Dropdown
Let’s test these frameworks—and Neuer—on a simple task:
A button with a dropdown.
The Use Cases:
- Version 1: Create a button with a dropdown.
- Version 2: Customize the dropdown’s content.
- Version 3: Override the click behavior.
- Version 4: Change styles to match a new context.
Sounds easy, right? Watch the big three fall apart. 🎭
React: A Render Function and a Prayer
React devs, gather ‘round. Here’s your React-based dropdown:
const DropdownButton = () => {
const [open, setOpen] = React.useState(false);
return (
<div className="dropdown">
<button className="btn" onClick={() => setOpen(!open)}>
Click Me <span className="caret"></span>
</button>
<div className={`dropdown-content ${open ? "show" : ""}`}>
Dropdown content
</div>
</div>
);
};
At first glance:
"Wow, React is so clean! Look at that JSX!"
But now let’s tweak it.
Version 2: Customize Dropdown Content
React says: "Time to rewrite everything!"
const CustomDropdownButton = () => {
const [open, setOpen] = React.useState(false);
return (
<div className="dropdown">
<button className="btn" onClick={() => setOpen(!open)}>
Click Me <span className="caret"></span>
</button>
<div className={`dropdown-content custom-style`}>
Totally custom content!
</div>
</div>
);
};
Duplicated logic, duplicated state.
Hope you remembered to copy the setOpen
function, or you’ll break everything. 🙃
Version 3: Override the Click Behavior
React says: "Sure, but you’ll need to rewrite the whole component again."
const CustomClickDropdown = () => {
const [open, setOpen] = React.useState(false);
const customToggle = () => console.log("Custom click logic!");
return (
<div className="dropdown">
<button className="btn" onClick={customToggle}>
Click Me <span className="caret"></span>
</button>
<div className={`dropdown-content ${open ? "show" : ""}`}>Dropdown content</div>
</div>
);
};
Fun Fact: That setOpen
logic? Yeah, it’s gone now. Good luck handling state without rewriting it all. 😏
Version 4: Change Styles
React says: "Hope you enjoy inline styles or CSS modules!"
const StyledDropdownButton = () => {
const [open, setOpen] = React.useState(false);
return (
<div className="dropdown" style={{ backgroundColor: "lightblue" }}>
<button className="btn" onClick={() => setOpen(!open)}>
Click Me <span className="caret"></span>
</button>
<div className={`dropdown-content ${open ? "show" : ""}`}>Dropdown content</div>
</div>
);
};
Inline styles? Really? Are we in 2013? React: where modularity goes to die. 💀
Vue: Directives All Day, Every Day
Here’s Vue’s starting dropdown:
<template>
<div class="dropdown">
<button class="btn" @click="toggleDropdown">
Click Me <span class="caret"></span>
</button>
<div :class="['dropdown-content', { show: isOpen }]">Dropdown content</div>
</div>
</template>
<script>
export default {
data() {
return { isOpen: false };
},
methods: {
toggleDropdown() {
this.isOpen = !this.isOpen;
},
},
};
</script>
Looks nice! But let’s see the cracks.
Version 2: Customize Dropdown Content
Vue says: "Go ahead and duplicate everything."
<template>
<div class="dropdown">
<button class="btn" @click="toggleDropdown">
Click Me <span class="caret"></span>
</button>
<div class="dropdown-content custom-style">Totally custom content!</div>
</div>
</template>
<script>
export default {
data() {
return { isOpen: false };
},
methods: {
toggleDropdown() {
this.isOpen = !this.isOpen;
},
},
};
</script>
Another entire component for one small tweak. DRY? What’s that? 🥴
Version 3: Override the Click Behavior
Vue says: "Rewrite the methods section too, kid."
<script>
export default {
data() {
return { isOpen: false };
},
methods: {
toggleDropdown() {
console.log("Custom click logic!");
},
},
};
</script>
Your dropdown’s behavior is isolated from the base logic. Hope you don’t need to share any logic with other components.
Version 4: Change Styles
Vue says: "Scoped styles to the rescue!"
But you still need to copy the template and styles into a new file.
Svelte: Rewrite It All, Forever
In Svelte, you get simplicity… until you need to reuse or tweak something.
The Neuer Way: One Class to Rule Them All
Version 2: Customize Dropdown Content
Extend. Override get template
. Done.
export class CustomDropdown extends DropdownButton {
static {
this.registerElement();
}
get template() {
return `
<div class="dropdown">
<button class="btn" c-click="toggleDropdown">Click Me <span class="caret"></span></button>
<div class="dropdown-content custom-style">Totally custom!</div>
</div>
`;
}
}
Version 3: Override Click Behavior
Override one method. Done.
export class CustomClickDropdown extends DropdownButton {
static {
this.registerElement();
}
toggleDropdown() {
console.log("Custom click logic!");
}
}
Version 4: Change Styles
Tweak get styles
. Done.
export class StyledDropdown extends DropdownButton {
static {
this.registerElement();
}
get styles() {
return `
${super.styles}
.dropdown-content {
background-color: lightblue;
color: darkblue;
}
`;
}
}
The Moral of the Story
React makes you duplicate.
Vue makes you rewrite.
Svelte makes you start over.
Neuer? Makes you smile. 😏
Stop copying, pasting, and rewriting your life away. It’s time for a Neuer way of doing things.
Welcome to the future. ✨
Top comments (1)
Where are the Svelte examples ... did you realize it isn't that bad at all? Inheritance and early abstraction is bad ... code duplication is good, for a while. Abstract when it makes sense. And then you can make those components easily customizable via props ...