| |

0: Vanilla JS Crash Course

Prerequisites for React — the DOM API is how JavaScript talks to HTML natively. React abstracts all of this, but understanding the raw browser APIs makes React’s model click and prepares you for general JavaScript interview questions.


1. Selecting Elements

Three ways to grab elements from the page:

// By ID — returns one element
const header = document.getElementById('header')

// By CSS selector — returns first match
const button = document.querySelector('.submit-btn')

// By CSS selector — returns ALL matches (NodeList)
const items = document.querySelectorAll('.list-item')

Exercise: Fill in the blanks.

// Select the element with id="app"
const app = document._______('app')

// Select the first <p> tag inside a div with class "content"
const paragraph = document._______('.content p')

// Select ALL elements with class "card"
const cards = document._______('.card')

2. Creating and Appending Elements

In React you write JSX. In vanilla JS, you manually create elements and attach them to the page.

const div = document.createElement('div')     // create a <div>
div.textContent = 'Hello World'                // set its text
div.style.color = 'red'                        // set inline style
div.className = 'greeting'                     // set CSS class
document.body.appendChild(div)                 // attach to page

Exercise: Fill in the blanks.

// Create a <button> element
const btn = document._______('button')

// Set its text to "Click Me"
btn._______ = 'Click Me'

// Give it a class of "primary"
btn._______ = 'primary'

// Add it inside the element with id="toolbar"
document.getElementById('toolbar')._______(btn)

3. Event Listeners

In React: onClick={handleClick}. In vanilla JS: addEventListener.

const button = document.querySelector('#my-btn')

button.addEventListener('click', () => {
  console.log('clicked!')
})

// With the event object (same 'e' you know from React)
button.addEventListener('click', (e) => {
  console.log(e.target)  // the element that was clicked
})

Exercise: Fill in the blanks.

const input = document.querySelector('#search')

// Listen for typing (same event as React's onChange)
input._______('input', (e) => {
  console.log('User typed:', e._______.value)
})

// Listen for Enter key
input._______('keydown', (e) => {
  if (e._______ === 'Enter') {
    console.log('Submitted:', e.target.value)
  }
})

4. Modifying Existing Elements

Change what’s already on the page — text, styles, attributes, visibility.

const title = document.querySelector('h1')

title.textContent = 'New Title'           // change text
title.style.backgroundColor = 'yellow'    // change style
title.setAttribute('data-id', '42')       // set attribute
title.classList.add('highlighted')         // add a CSS class
title.classList.remove('hidden')           // remove a CSS class
title.classList.toggle('active')           // toggle a CSS class

Exercise: Fill in the blanks.

const card = document.querySelector('.card')

// Change the text inside the card
card._______ = 'Updated content'

// Add the CSS class "selected"
card.classList._______('selected')

// Set a custom data attribute
card._______('data-status', 'active')

// Change the background color
card._______.backgroundColor = 'lightblue'

5. Removing Elements

const item = document.querySelector('.old-item')
item.remove()  // that's it

6. Building a List Dynamically

This is the vanilla JS version of .map() in React. Instead of returning JSX, you create elements in a loop and append them.

const fruits = ['Apple', 'Banana', 'Cherry']
const list = document.querySelector('#fruit-list')  // an existing <ul>

fruits.forEach(fruit => {
  const li = document.createElement('li')
  li.textContent = fruit
  list.appendChild(li)
})

Exercise: Fill in the blanks to build a clickable list where clicking an item alerts its name.

const names = ['Alice', 'Bob', 'Charlie']
const container = document.querySelector('#names')

names.forEach(name => {
  const div = document._______('div')
  div._______ = name
  div._______('click', () => {
    alert('You clicked: ' + name)
  })
  container._______(div)
})

7. Putting It Together — Mini Todo (no React)

This is the vanilla JS equivalent of your React TodoList. Same logic, different API.

Exercise: Fill in the blanks.

const input = document._______('#todo-input')
const addBtn = document._______('#add-btn')
const list = document._______('#todo-list')

addBtn._______('click', () => {
  const text = input._______
  if (!text) return

  const li = document._______('li')
  li._______ = text

  // Add a delete button
  const deleteBtn = document._______('button')
  deleteBtn._______ = 'X'
  deleteBtn._______('click', () => {
    li._______()
  })

  li._______(deleteBtn)
  list._______(li)
  input.value = ''
})

Key Differences from React

ReactVanilla JS
onClick={fn}el.addEventListener('click', fn)
{text} in JSXel.textContent = text
style={{color: 'red'}}el.style.color = 'red'
className="foo"el.className = 'foo'
.map() returns JSXforEach + createElement + appendChild
State triggers re-renderYou manually update the DOM
Component unmount cleans upYou manually call removeEventListener