As someone who has navigated the intricacies of React, Angular, and Vue throughout my career, I've come to appreciate the nuanced differences between these popular frontend frameworks. In this article, I'll outline why opting for Angular or Vue might offer a more structured and scalable approach compared to React for your next web application project.
1. Templates
Templates in Angular and Vue offer a clear separation of concerns between logic and presentation, which fosters cleaner code and easier maintenance. Unlike React's JSX, where JavaScript logic can be intertwined with markup, Angular and Vue templates enforce a strict separation. Let's illustrate this with examples:
React JSX:
return (
<div>
{array.map(item => {
if (condition) {
return <p>{item}</p>;
} else {
return <span>{item}</span>;
}
})}
</div>
);
Angular Template:
<div *ngFor="let item of array">
<p *ngIf="condition; else other">{{ item }}</p>
<ng-template #other><span>{{ item }}</span></ng-template>
</div>
Vue Template:
<div v-for="item in array">
<p v-if="condition">{{ item }}</p>
<span v-else>{{ item }}</span>
</div>
2. Binding Form Controls
Angular and Vue provide straightforward ways to bind form controls, making it easy to manage form data with multiple fields. Let's create a form object with four fields: text input, radio button, checkbox, and select dropdown.
Angular:
@Component({
selector: 'app-form',
template: `
<form>
<input type="text" [(ngModel)]="formData.text" placeholder="Text Input">
<br>
<input type="radio" [(ngModel)]="formData.radio" value="option1"> Option 1
<input type="radio" [(ngModel)]="formData.radio" value="option2"> Option 2
<br>
<input type="checkbox" [(ngModel)]="formData.checkbox"> Checkbox
<br>
<select [(ngModel)]="formData.select">
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
</select>
</form>
`,
})
export class FormComponent {
formData = {
text: '',
radio: '',
checkbox: false,
select: '',
};
}
Vue:
<template>
<form>
<input type="text" v-model="formData.text" placeholder="Text Input">
<br>
<input type="radio" v-model="formData.radio" value="option1"> Option 1
<input type="radio" v-model="formData.radio" value="option2"> Option 2
<br>
<input type="checkbox" v-model="formData.checkbox"> Checkbox
<br>
<select v-model="formData.select">
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
</select>
</form>
</template>
<script>
export default {
data() {
return {
formData: {
text: '',
radio: '',
checkbox: false,
select: '',
},
};
},
};
</script>
React:
const FormComponent = () => {
const [formData, setFormData] = useState({
text: '',
radio: '',
checkbox: false,
select: '',
});
const handleChange = (e) => {
const { name, value, type, checked } = e.target;
setFormData({
...formData,
[name]: type === 'checkbox' ? checked : value,
});
};
return (
<form>
<input type="text" name="text" value={formData.text} onChange={handleChange} placeholder="Text Input" />
<br />
<input type="radio" name="radio" value="option1" checked={formData.radio === 'option1'} onChange={handleChange} /> Option 1
<input type="radio" name="radio" value="option2" checked={formData.radio === 'option2'} onChange={handleChange} /> Option 2
<br />
<input type="checkbox" name="checkbox" checked={formData.checkbox} onChange={handleChange} /> Checkbox
<br />
<select name="select" value={formData.select} onChange={handleChange}>
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
</select>
</form>
);
};
In React, without using libraries like Formik or React Hook Form, managing form state requires setting up state variables with useState
and writing a handler function to update the state whenever form fields change. This can add boilerplate code and increase complexity, especially for forms with multiple fields. While form libraries offer advanced form handling capabilities, integrating them into a project requires additional setup and learning.
In my opinion, developers may not want to spend time choosing and learning additional documentation for form libraries, especially when handling forms is a typical everyday task for frontend developers. Angular and Vue's built-in form handling capabilities offer a simpler and more integrated approach, allowing developers to focus on building their applications without the need for additional dependencies.
3. Accessing Child Components
Angular's ViewChild
, Vue's refs, and React's useImperativeHandle
are mechanisms to interact with child components. While all three provide ways to achieve this, Angular and Vue offer cleaner and more intuitive approaches compared to React's useImperativeHandle
, which is less recommended by React's documentation. Here are examples:
Angular:
@Component({
selector: 'app-parent',
template: `
<app-child #child></app-child>
<button (click)="callChildMethod()">Call Child Method</button>
`,
})
export class ParentComponent {
@ViewChild('child') childComponent: ChildComponent;
callChildMethod() {
this.childComponent.someMethod();
}
}
Vue:
<template>
<div>
<child ref="child"></child>
<button @click="callChildMethod">Call Child Method</button>
</div>
</template>
<script>
import Child from './Child.vue';
export default {
components: {
Child,
},
methods: {
callChildMethod() {
this.$refs.child.someMethod();
},
},
};
</script>
React:
const ChildComponent = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
someMethod() {
// Method logic
},
}));
return <p>I am a child</p>;
});
const ParentComponent = () => {
const childRef = useRef(null);
// Access child component's method
const handleButtonClick = () => {
childRef.current.someMethod();
};
return (
<div>
<ChildComponent ref={childRef} />
<button onClick={handleButtonClick}>Call Child Method</button>
</div>
);
};
In React, while the functional component paradigm doesn't inherently provide "methods" like Angular class components or Vue components with "methods" property, a simpler approach for accessing child methods without the useImperativeHandle
hook is desired. useImperativeHandle
can be less clear, and it requires wrapping the child component in the forwardRef
function. Unlike Angular and Vue, where you can access child methods without altering the child component itself, React requires this additional setup to achieve similar functionality.
I also want to note about Vue. The Composition API is a relatively new technology in Vue and access to child components is a little different than what I described above. But I assume that not all teams have yet implemented the Composition API in their projects and use the approach that I described.
I have described three reasons why, in my opinion, you should choose Angular or Vue instead of React. At the end of my article, I would like to talk a little about the size of the final production build of all these three frameworks. An optimized and non-slow web application on computers, smartphones of different capacities, with different browsers provides a cool user experience, which, of course, is good for business.
When it comes to bundle sizes, it's essential to consider the impact on performance and user experience. Here's a deeper look at how each framework's bundle size can affect your project:
- React: Despite its smaller bundle size for simpler applications like "Hello World" (30-100 KB) projects, React's bundle size advantage diminishes as the complexity of the application increases. With a full-fledged online store application, React's bundle size can range from 500 KB to 2 MB or more, similar to Angular and Vue. Therefore, if a super small product bundle size is your priority, React might not offer significant advantages over Vue or Angular in this regard.
- Angular: Angular's bundle size is generally larger compared to React, primarily due to its comprehensive framework features. For a basic "Hello World" app, the bundle size might range from 100 KB to 300 KB, while for an online store application, it could be anywhere between 1 MB to 3 MB. Despite the larger size, Angular's built-in optimizations like Ahead-of-Time (AOT) compilation and lazy loading can help mitigate this impact.
- Vue: Vue strikes a balance between React's flexibility and Angular's comprehensive features, resulting in a bundle size that typically falls between the other two frameworks. For a "Hello World" app, Vue's bundle size might range from 50 KB to 150 KB, while for an online store application, it could be around 500 KB to 1.5 MB. Vue's simplicity and performance optimizations contribute to its relatively smaller footprint compared to Angular.
In conclusion, it's important to acknowledge the contributions of React developers and the creators of the React library. However, in my experience, building a React application without the guidance of experienced developers, such as a tech lead or senior developer who has invested significant time and effort into understanding the intricacies of React, can be challenging. React's flexibility can lead to pitfalls if not managed properly, and inexperienced developers may encounter difficulties in creating maintainable and scalable React applications.
On the other hand, frameworks like Vue and Angular offer a more structured approach with strict concepts and conventions. These frameworks guide developers toward best practices and help mitigate common pitfalls, making it easier to build robust applications even for those with less experience.
Ultimately, the choice between React, Vue, and Angular depends on various factors, including project requirements, team expertise, and personal preferences. However, for developers seeking a more guided and structured approach, Vue and Angular may offer a smoother learning curve and a more supportive environment for building complex applications.