Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Part 3: Vanilla JavaScript (25 min)

Goal

Build a working task tracker with raw JavaScript and DOM manipulation. The point is to feel the pain — by the end you'll understand exactly what React eliminates.

What's here

  • index.html — same shell, with <script src="script.js" defer></script> and an empty <ul>
  • style.css — extended with .done and .delete-btn styles
  • script.js — the logic

Run it

Right-click index.htmlOpen with Live Server. Add tasks, tick them, delete them.

JS for R/Python users — the cheat sheet

Concept JS R/Python equivalent
Variable const x = 5 / let x = 5 x <- 5 / x = 5
Lambda (a, b) => a + b \(a, b) a + b / lambda a, b: a + b
Map arr.map(x => x * 2) purrr::map() / list comp
Filter arr.filter(x => x > 0) purrr::keep() / list comp
Object {name: 'A', age: 3} named list / dict
Equality === (strict) == (always use === in JS, never ==)
Null-ish null, undefined NULL, missing
String interp `Hi ${name}` glue("Hi {name}") / f-string

Use const by default, let only when reassigning. Never var.

Read the code

Open script.js and read it top to bottom. Notice the structure:

  1. Grab DOM elements by ID (document.getElementById)
  2. Hold data in a plain JS array (tasks)
  3. Define a render() function that wipes the list and rebuilds it from scratch
  4. Wire up event handlers (onclick, onchange) that mutate data then call render()

The pain points (this is the whole lesson)

Read the comments marked <-- have to remember to call this in script.js. There are four places we call render(). Forget one and the UI silently lies about your data.

Other pain:

  • The data (tasks array) and the DOM are two separate worlds you must manually keep in sync.
  • We rebuild the entire list every time, even when one task changes. Inefficient for large lists.
  • Event handlers attached in render() are recreated every cycle. Easy to leak memory in real apps.
  • No componentisation — if you wanted a second task list elsewhere, you'd copy-paste everything.

Try this

  1. Remove one of the render() calls and see what breaks.
  2. Add a "clear completed" button. You'll need: a new button in HTML, a new event handler in JS, and yes — another render() call.
  3. Open devtools → Console tab. Type tasks and hit Enter — you can inspect your data live. Type tasks.push({id: 999, text: 'hi', done: false}) then render() to add a task from the console.

What React fixes

React lets you write: "given this tasks array, the UI looks like this JSX." You change the array, React figures out the minimal DOM updates. No manual render(), no getElementById, no two worlds to sync.

Next

Part 4: React