liveBook · Manning

Reduction operation

As explained in Build a Frontend Web Framework (From Scratch)

A reduce function is a function conceptually applied to accumulated input to produce a result, providing the name's functional-programming origin for reducers.

When a user changes an application, its state must change too. A reducer is the function that calculates the next state from the current state and a command’s payload. The name comes from the reduce function in functional programming; here, the practical job is updating application state. section 5.1.2 section 5.3

Keep the reducer pure: return a new state rather than changing the state passed in. For a to-do list held in an array, removing the item at a given index can be as small as `function removeTodo(state, index) { return state.toSpliced(index, 1) }`. The original array remains unchanged. section 5.1.2

Match a command to a reducer

A to-do application can give each action its own reducer: updating the current input, adding an item, starting or saving an edit, and removing an item. An `add-todo` reducer needs no payload if the new description is already in state; it returns a new object with the description added to `todos` and the input cleared. section 6.3.2

To connect reducers to the application, map command names to reducer functions. When the dispatcher receives a command, its subscribed handler calls the matching reducer with the current state and payload, then stores the returned state. An after-command handler re-renders the view. This simple version re-renders even when a command leaves state unchanged. section 5.2.3

Listing 5.6 Adding the state manager to the application instance (app.js)
import { destroyDOM } from './destroy-dom'
import { Dispatcher } from './dispatcher'
import { mountDOM } from './mount-dom'

export function createApp({ state, view, reducers = {} }) {
  let parentEl = null
  let vdom = null

  const dispatcher = new Dispatcher()
  const subscriptions = [dispatcher.afterEveryCommand(renderApp)]     #1

  for (const actionName in reducers) {
    const reducer = reducers[actionName]

    const subs = dispatcher.subscribe(actionName, (payload) => {
      state = reducer(state, payload)           #2
    })
    subscriptions.push(subs)    #3
  }

 // --snip-- //
}

The application-instance listing shows the key handoff: `state = reducer(state, payload)` inside a command subscription. section 5.2.3

How Build a Frontend Web Framework (From Scratch) covers it

How deep it goes
Defines the state-and-payload contract and implements reducer wiring, while deferring more efficient rendering.
Examples
Uses to-do removal and a fuller set of to-do editing actions, plus a tic-tac-toe design exercise.
What it assumes
Builds on JavaScript functions, application state, and commands while defining the reducer’s inputs and output.
What you can do after
Build it from scratch: write pure reducers and connect them to dispatched commands in a small application framework.
How it connects
Connects pure functions and immutable state to commands, dispatchers, state management, and rendering.

Also explained in

Compare how 9 books explain reduction operation →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Build a Frontend Web Framework (From Scratch). The section links point to the parts of the book it draws on.