Skip to content

React vs Vanilla JavaScript

Overview

This chapter will deeply compare the differences between React framework and native JavaScript development, helping you understand why choose React, as well as their respective advantages, disadvantages, and applicable scenarios.

🔄 Development Approach Comparison

Native JavaScript Development

html
<!DOCTYPE html>
<html>
<head>
    <title>Vanilla JavaScript Todo</title>
    <style>
        .container { max-width: 600px; margin: 0 auto; padding: 20px; }
        .todo-item { padding: 10px; border: 1px solid #ddd; margin: 5px 0; }
        .completed { text-decoration: line-through; opacity: 0.6; }
    </style>
</head>
<body>
    <div class="container">
        <h1>Todo List</h1>
        <form id="todoForm">
            <input type="text" id="todoInput" placeholder="Add new task..." required>
            <button type="submit">Add</button>
        </form>
        <div id="todoList"></div>
        <div id="stats"></div>
    </div>

    <script>
        // Global state
        let todos = [];
        let nextId = 1;

        // DOM element references
        const todoForm = document.getElementById('todoForm');
        const todoInput = document.getElementById('todoInput');
        const todoList = document.getElementById('todoList');
        const stats = document.getElementById('stats');

        // Add event listeners
        todoForm.addEventListener('submit', handleAddTodo);

        function handleAddTodo(e) {
            e.preventDefault();
            const text = todoInput.value.trim();
            if (text) {
                addTodo(text);
                todoInput.value = '';
            }
        }

        function addTodo(text) {
            const todo = {
                id: nextId++,
                text: text,
                completed: false
            };
            todos.push(todo);
            renderTodos();
            renderStats();
        }

        function toggleTodo(id) {
            todos = todos.map(todo =>
                todo.id === id ? { ...todo, completed: !todo.completed } : todo
            );
            renderTodos();
            renderStats();
        }

        function deleteTodo(id) {
            todos = todos.filter(todo => todo.id !== id);
            renderTodos();
            renderStats();
        }

        function renderTodos() {
            todoList.innerHTML = '';
            todos.forEach(todo => {
                const todoElement = document.createElement('div');
                todoElement.className = `todo-item ${todo.completed ? 'completed' : ''}`;
                todoElement.innerHTML = `
                    <input type="checkbox" ${todo.completed ? 'checked' : ''} 
                           onchange="toggleTodo(${todo.id})">
                    <span>${todo.text}</span>
                    <button onclick="deleteTodo(${todo.id})" style="float: right;">Delete</button>
                `;
                todoList.appendChild(todoElement);
            });
        }

        function renderStats() {
            const total = todos.length;
            const completed = todos.filter(t => t.completed).length;
            const active = total - completed;
            stats.innerHTML = `Total: ${total} | Completed: ${completed} | Active: ${active}`;
        }

        // Initial render
        renderTodos();
        renderStats();
    </script>
</body>
</html>

React Development Approach

jsx
function ReactTodoApp() {
    const [todos, setTodos] = React.useState([]);
    const [inputValue, setInputValue] = React.useState('');
    const [nextId, setNextId] = React.useState(1);
    
    const addTodo = (text) => {
        if (text.trim()) {
            setTodos(prev => [...prev, {
                id: nextId,
                text: text.trim(),
                completed: false
            }]);
            setNextId(prev => prev + 1);
            setInputValue('');
        }
    };
    
    const toggleTodo = (id) => {
        setTodos(prev => prev.map(todo =>
            todo.id === id ? { ...todo, completed: !todo.completed } : todo
        ));
    };
    
    const deleteTodo = (id) => {
        setTodos(prev => prev.filter(todo => todo.id !== id));
    };
    
    const handleSubmit = (e) => {
        e.preventDefault();
        addTodo(inputValue);
    };
    
    const stats = {
        total: todos.length,
        completed: todos.filter(t => t.completed).length,
        active: todos.filter(t => !t.completed).length
    };
    
    return (
        <div style={{ maxWidth: '600px', margin: '0 auto', padding: '20px' }}>
            <h1>React Todo List</h1>
            
            <form onSubmit={handleSubmit}>
                <input
                    type="text"
                    value={inputValue}
                    onChange={(e) => setInputValue(e.target.value)}
                    placeholder="Add new task..."
                    required
                />
                <button type="submit">Add</button>
            </form>
            
            <div>
                {todos.map(todo => (
                    <div 
                        key={todo.id} 
                        style={{
                            padding: '10px',
                            border: '1px solid #ddd',
                            margin: '5px 0',
                            textDecoration: todo.completed ? 'line-through' : 'none',
                            opacity: todo.completed ? 0.6 : 1
                        }}
                    >
                        <input
                            type="checkbox"
                            checked={todo.completed}
                            onChange={() => toggleTodo(todo.id)}
                        />
                        <span>{todo.text}</span>
                        <button 
                            onClick={() => deleteTodo(todo.id)}
                            style={{ float: 'right' }}
                        >
                            Delete
                        </button>
                    </div>
                ))}
            </div>
            
            <div>
                Total: {stats.total} | Completed: {stats.completed} | Active: {stats.active}
            </div>
        </div>
    );
}

📊 Detailed Comparison Analysis

Code Complexity Comparison

jsx
function ComparisonExample() {
    const [showVanilla, setShowVanilla] = React.useState(false);
    
    const comparisons = [
        {
            aspect: 'Code Amount',
            vanilla: '~100+ lines HTML/CSS/JS',
            react: '~60 lines JSX',
            advantage: 'React'
        },
        {
            aspect: 'State Management',
            vanilla: 'Manual global variable management',
            react: 'useState Hook automatic management',
            advantage: 'React'
        },
        {
            aspect: 'DOM Manipulation',
            vanilla: 'Manual createElement/innerHTML',
            react: 'Declarative JSX, automatic updates',
            advantage: 'React'
        },
        {
            aspect: 'Event Handling',
            vanilla: 'addEventListener/onclick',
            react: 'In-component event handling',
            advantage: 'React'
        },
        {
            aspect: 'Code Reuse',
            vanilla: 'Function reuse, difficult',
            react: 'Componentized, highly reusable',
            advantage: 'React'
        },
        {
            aspect: 'Learning Cost',
            vanilla: 'Basic web technologies',
            react: 'Need to learn React ecosystem',
            advantage: 'Vanilla'
        },
        {
            aspect: 'Performance',
            vanilla: 'Direct DOM manipulation',
            react: 'Virtual DOM + optimization',
            advantage: 'Depends'
        },
        {
            aspect: 'Bundle Size',
            vanilla: 'No additional dependencies',
            react: '~40KB (gzipped)',
            advantage: 'Vanilla'
        }
    ];
    
    return (
        <div style={{ padding: '20px' }}>
            <h2>React vs Vanilla JavaScript Comparison</h2>
            
            <div style={{ overflowX: 'auto' }}>
                <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                    <thead>
                        <tr style={{ backgroundColor: '#f8f9fa' }}>
                            <th style={{ padding: '12px', border: '1px solid #ddd' }}>Aspect</th>
                            <th style={{ padding: '12px', border: '1px solid #ddd' }}>Vanilla JavaScript</th>
                            <th style={{ padding: '12px', border: '1px solid #ddd' }}>React</th>
                            <th style={{ padding: '12px', border: '1px solid #ddd' }}>Advantage</th>
                        </tr>
                    </thead>
                    <tbody>
                        {comparisons.map((item, index) => (
                            <tr key={index}>
                                <td style={{ padding: '12px', border: '1px solid #ddd', fontWeight: 'bold' }}>
                                    {item.aspect}
                                </td>
                                <td style={{ padding: '12px', border: '1px solid #ddd' }}>
                                    {item.vanilla}
                                </td>
                                <td style={{ padding: '12px', border: '1px solid #ddd' }}>
                                    {item.react}
                                </td>
                                <td style={{ 
                                    padding: '12px', 
                                    border: '1px solid #ddd',
                                    backgroundColor: item.advantage === 'React' ? '#d4edda' : 
                                                   item.advantage === 'Vanilla' ? '#fff3cd' : '#f8f9fa',
                                    fontWeight: 'bold'
                                }}>
                                    {item.advantage}
                                </td>
                            </tr>
                        ))}
                    </tbody>
                </table>
            </div>
        </div>
    );
}

🎯 Applicable Scenario Analysis

Vanilla JavaScript Applicable Scenarios

jsx
function VanillaJSScenarios() {
    const scenarios = [
        {
            title: 'Simple Static Websites',
            description: 'Corporate websites, personal blogs, content display sites',
            pros: ['Fast development', 'No framework dependencies', 'SEO friendly'],
            example: 'Contact form for company website'
        },
        {
            title: 'Small Interactive Features',
            description: 'Simple interactive effects and animations on pages',
            pros: ['Lightweight', 'Direct control', 'Good performance'],
            example: 'Image carousel, dropdown menus, modal dialogs'
        },
        {
            title: 'Existing Project Feature Enhancement',
            description: 'Adding interactive features to existing non-SPA websites',
            pros: ['Progressive enhancement', 'No refactoring needed', 'Good compatibility'],
            example: 'Form validation, AJAX load more'
        },
        {
            title: 'Performance Sensitive Applications',
            description: 'Scenarios with extremely high bundle size and performance requirements',
            pros: ['Zero dependencies', 'Full control', 'Minimal size'],
            example: 'Mobile H5 pages, embedded pages'
        }
    ];
    
    return (
        <div style={{ padding: '20px' }}>
            <h2>Vanilla JavaScript Applicable Scenarios</h2>
            <div style={{ display: 'grid', gap: '20px' }}>
                {scenarios.map((scenario, index) => (
                    <div key={index} style={{
                        border: '1px solid #ddd',
                        borderRadius: '8px',
                        padding: '20px',
                        backgroundColor: '#fff8dc'
                    }}>
                        <h3 style={{ margin: '0 0 10px 0', color: '#d63384' }}>
                            {scenario.title}
                        </h3>
                        <p style={{ margin: '0 0 15px 0', color: '#666' }}>
                            {scenario.description}
                        </p>
                        <div style={{ marginBottom: '15px' }}>
                            <strong>Advantages:</strong>
                            <ul style={{ margin: '5px 0 0 20px' }}>
                                {scenario.pros.map((pro, i) => (
                                    <li key={i}>{pro}</li>
                                ))}
                            </ul>
                        </div>
                        <div style={{ 
                            backgroundColor: '#f8f9fa', 
                            padding: '10px', 
                            borderRadius: '4px',
                            fontStyle: 'italic'
                        }}>
                            <strong>Example:</strong> {scenario.example}
                        </div>
                    </div>
                ))}
            </div>
        </div>
    );
}

React Applicable Scenarios

jsx
function ReactScenarios() {
    const scenarios = [
        {
            title: 'Complex Single Page Applications (SPA)',
            description: 'Applications with complex state management and user interactions',
            pros: ['Componentized', 'State management', 'Rich ecosystem'],
            example: 'Admin systems, online editors'
        },
        {
            title: 'Data-Driven Applications',
            description: 'Data-intensive applications requiring frequent UI updates',
            pros: ['Virtual DOM', 'Automatic updates', 'Performance optimization'],
            example: 'Real-time charts, stock trading interfaces'
        },
        {
            title: 'Team Collaboration Projects',
            description: 'Multi-person development, projects requiring code reuse and maintenance',
            pros: ['Component reuse', 'Standardized development', 'Easy maintenance'],
            example: 'Enterprise web applications, e-commerce platforms'
        },
        {
            title: 'Rapid Prototype Development',
            description: 'Projects requiring quick validation of ideas and features',
            pros: ['High development efficiency', 'Rich component libraries', 'Fast iteration'],
            example: 'MVP products, proof of concept'
        }
    ];
    
    return (
        <div style={{ padding: '20px' }}>
            <h2>React Applicable Scenarios</h2>
            <div style={{ display: 'grid', gap: '20px' }}>
                {scenarios.map((scenario, index) => (
                    <div key={index} style={{
                        border: '1px solid #ddd',
                        borderRadius: '8px',
                        padding: '20px',
                        backgroundColor: '#e7f3ff'
                    }}>
                        <h3 style={{ margin: '0 0 10px 0', color: '#0066cc' }}>
                            {scenario.title}
                        </h3>
                        <p style={{ margin: '0 0 15px 0', color: '#666' }}>
                            {scenario.description}
                        </p>
                        <div style={{ marginBottom: '15px' }}>
                            <strong>Advantages:</strong>
                            <ul style={{ margin: '5px 0 0 20px' }}>
                                {scenario.pros.map((pro, i) => (
                                    <li key={i}>{pro}</li>
                                ))}
                            </ul>
                        </div>
                        <div style={{ 
                            backgroundColor: '#f8f9fa', 
                            padding: '10px', 
                            borderRadius: '4px',
                            fontStyle: 'italic'
                        }}>
                            <strong>Example:</strong> {scenario.example}
                        </div>
                    </div>
                ))}
            </div>
        </div>
    );
}

🔄 Migration Strategy

Migration from Vanilla to React

jsx
function MigrationStrategy() {
    const [currentStep, setCurrentStep] = React.useState(0);
    
    const migrationSteps = [
        {
            title: '1. Evaluate Existing Code',
            content: 'Analyze existing functional modules, identify parts that can be componentized',
            code: `
// Identify repetitive DOM operations
function createUserCard(user) {
    const card = document.createElement('div');
    card.innerHTML = \`
        <h3>\${user.name}</h3>
        <p>\${user.email}</p>
    \`;
    return card;
}
// 👆 This repetitive pattern is suitable for componentization
            `
        },
        {
            title: '2. Progressively Introduce React',
            content: 'Start using React in a specific area of the page',
            code: `
// Mount React component in existing page
const userListContainer = document.getElementById('user-list');
const root = ReactDOM.createRoot(userListContainer);
root.render(<UserList />);
            `
        },
        {
            title: '3. State Management Migration',
            content: 'Gradually migrate global state to React state management',
            code: `
// Vanilla: Global variables
let users = [];

// React: useState
function UserManager() {
    const [users, setUsers] = useState([]);
    // ...
}
            `
        },
        {
            title: '4. Event System Migration',
            content: 'Migrate event listeners to React event system',
            code: `
// Vanilla: addEventListener
button.addEventListener('click', handleClick);

// React: JSX event attributes
<button onClick={handleClick}>Click</button>
            `
        },
        {
            title: '5. Complete Refactoring',
            content: 'Refactor entire application to React SPA',
            code: `
// Complete React application structure
function App() {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<Home />} />
                <Route path="/users" element={<UserList />} />
            </Routes>
        </BrowserRouter>
    );
}
            `
        }
    ];
    
    return (
        <div style={{ padding: '20px' }}>
            <h2>Migration Strategy: From Vanilla JavaScript to React</h2>
            
            <div style={{ display: 'flex', marginBottom: '20px' }}>
                {migrationSteps.map((_, index) => (
                    <button
                        key={index}
                        onClick={() => setCurrentStep(index)}
                        style={{
                            padding: '10px 15px',
                            margin: '0 5px',
                            backgroundColor: currentStep === index ? '#007bff' : '#f8f9fa',
                            color: currentStep === index ? 'white' : '#333',
                            border: '1px solid #ddd',
                            borderRadius: '4px',
                            cursor: 'pointer'
                        }}
                    >
                        Step {index + 1}
                    </button>
                ))}
            </div>
            
            <div style={{
                border: '1px solid #ddd',
                borderRadius: '8px',
                padding: '20px',
                backgroundColor: '#f8f9fa'
            }}>
                <h3>{migrationSteps[currentStep].title}</h3>
                <p>{migrationSteps[currentStep].content}</p>
                <pre style={{
                    backgroundColor: '#282c34',
                    color: '#abb2bf',
                    padding: '15px',
                    borderRadius: '4px',
                    overflow: 'auto'
                }}>
                    {migrationSteps[currentStep].code.trim()}
                </pre>
            </div>
        </div>
    );
}

📝 Decision Guide

Technology Selection Decision Tree

jsx
function TechDecisionTree() {
    const [answers, setAnswers] = React.useState({});
    
    const questions = [
        {
            id: 'complexity',
            question: 'How complex is the project?',
            options: [
                { value: 'simple', label: 'Simple (static pages or simple interactions)', weight: { vanilla: 3, react: 1 } },
                { value: 'medium', label: 'Medium (multiple interaction modules)', weight: { vanilla: 2, react: 2 } },
                { value: 'complex', label: 'Complex (complex state management)', weight: { vanilla: 1, react: 3 } }
            ]
        },
        {
            id: 'team',
            question: 'Team size and experience?',
            options: [
                { value: 'solo', label: 'Personal project', weight: { vanilla: 2, react: 2 } },
                { value: 'small', label: 'Small team (2-5 people)', weight: { vanilla: 2, react: 3 } },
                { value: 'large', label: 'Large team (5+ people)', weight: { vanilla: 1, react: 3 } }
            ]
        },
        {
            id: 'timeline',
            question: 'Development time requirements?',
            options: [
                { value: 'urgent', label: 'Very urgent (1-2 weeks)', weight: { vanilla: 3, react: 1 } },
                { value: 'normal', label: 'Normal (1-3 months)', weight: { vanilla: 2, react: 3 } },
                { value: 'long', label: 'Long-term project (3+ months)', weight: { vanilla: 1, react: 3 } }
            ]
        },
        {
            id: 'maintenance',
            question: 'Maintenance and expansion needs?',
            options: [
                { value: 'minimal', label: 'Rare maintenance', weight: { vanilla: 3, react: 1 } },
                { value: 'moderate', label: 'Regular updates', weight: { vanilla: 2, react: 2 } },
                { value: 'frequent', label: 'Frequent iterations', weight: { vanilla: 1, react: 3 } }
            ]
        }
    ];
    
    const calculateRecommendation = () => {
        let vanillaScore = 0;
        let reactScore = 0;
        
        Object.values(answers).forEach(answer => {
            if (answer) {
                vanillaScore += answer.weight.vanilla;
                reactScore += answer.weight.react;
            }
        });
        
        if (vanillaScore > reactScore) {
            return {
                recommendation: 'Vanilla JavaScript',
                reason: 'Based on your needs, Vanilla JavaScript is more suitable for your project',
                color: '#ffc107'
            };
        } else if (reactScore > vanillaScore) {
            return {
                recommendation: 'React',
                reason: 'Based on your needs, React framework is more suitable for your project',
                color: '#007bff'
            };
        } else {
            return {
                recommendation: 'Either Works',
                reason: 'Your project is suitable for both technologies, choose based on team familiarity',
                color: '#28a745'
            };
        }
    };
    
    const handleAnswerChange = (questionId, option) => {
        setAnswers(prev => ({
            ...prev,
            [questionId]: option
        }));
    };
    
    const result = Object.keys(answers).length === questions.length ? calculateRecommendation() : null;
    
    return (
        <div style={{ padding: '20px' }}>
            <h2>Technology Selection Decision Tool</h2>
            
            {questions.map(question => (
                <div key={question.id} style={{ marginBottom: '25px' }}>
                    <h3>{question.question}</h3>
                    <div>
                        {question.options.map(option => (
                            <label key={option.value} style={{
                                display: 'block',
                                margin: '8px 0',
                                padding: '10px',
                                border: '1px solid #ddd',
                                borderRadius: '4px',
                                cursor: 'pointer',
                                backgroundColor: answers[question.id]?.value === option.value ? '#e7f3ff' : '#f8f9fa'
                            }}>
                                <input
                                    type="radio"
                                    name={question.id}
                                    value={option.value}
                                    checked={answers[question.id]?.value === option.value}
                                    onChange={() => handleAnswerChange(question.id, option)}
                                    style={{ marginRight: '10px' }}
                                />
                                {option.label}
                            </label>
                        ))}
                    </div>
                </div>
            ))}
            
            {result && (
                <div style={{
                    padding: '20px',
                    backgroundColor: result.color + '20',
                    border: `2px solid ${result.color}`,
                    borderRadius: '8px',
                    marginTop: '30px'
                }}>
                    <h2 style={{ color: result.color, margin: '0 0 10px 0' }}>
                        Recommended Technology: {result.recommendation}
                    </h2>
                    <p style={{ margin: 0, fontSize: '16px' }}>{result.reason}</p>
                </div>
            )}
        </div>
    );
}

📊 Main Differences

  • ✅ Development Approach: Imperative vs Declarative
  • ✅ State Management: Manual vs Automatic
  • ✅ DOM Manipulation: Direct vs Virtual DOM
  • ✅ Code Organization: Functions vs Componentized

🎯 Selection Principles

  1. Project Complexity: Use vanilla for simple, React for complex
  2. Team Size: Large teams benefit more from React's standardization
  3. Maintenance Needs: Choose React for long-term maintained projects
  4. Performance Requirements: Extreme performance may require vanilla optimization
  5. Learning Cost: Consider team's technical background

🔄 Migration Suggestions

  • Progressive introduction: No need to completely rewrite
  • Evaluate benefits: Ensure benefits of migration outweigh costs
  • Team training: Ensure team masters new technology
  • Risk control: Pilot in small modules before large-scale application

React and Vanilla JavaScript each have their advantages. Choosing the right technology stack is one of the key factors for project success.

Content is for learning and research only.