Managing state and refactoring code

In notebook:
FrontEndMasters Modular Web Development
Created at:
2017-10-01
Updated:
2019-08-15
Tags:
JavaScript libraries Fundamentals

So far we saw the basics, but this will not scale very well. We already have several variable declared on the top that hold the "state".

  //	****		yo.js		****

var html = require('yo-yo')
// **** 1. wrap the variables in a state  ↴
var state = {n : 5, x  0}

var root = document.body.appendChild(document.createElement('div'))
update()

setInterval(function () {
  // **** 2. the update stuff inside the state  ↴
  state.n++
  update()
}, 1000)


function update () {
  html.update(root, html`<div> 
    <h1>${state.n}</h1>
    add the coaddunter display
    <div>${state.x}</div>
    <button onclick=${onclick}>CLICK ME</button>
  </div>`)
  function onclick (ev) {
    // **** 2. update the state  ↴
    state.x++
    update()
  }
}

This is a cleaner to way to manage the application state.

You can also do fancy stuff like, saving history and stepping through, etc.

##Using events

It's not reliable to change the state inside your event handlers:

function onclick (ev) {
    state.x++
    update()

He proposes to use event emitters to get around this. (my note: I prefer the dispatch/redux pattern)

  //	****		yo.js		****

var html = require('yo-yo')
var state = {n : 5, x  0}

// **** 1. add the event emmitter library  ↴
const EventEmitter = require('events')
var bus = new EventEmitter // this will carry the events
// **** 3. implement the increment-n event  ↴
bus.on('increment-n', function () {
  // we move both state change
  state.n++
  // and re-render triggering
  // update()
  // **** 4. let's use an event for the updating as well ↴
  bus.emit('update')
})
// **** 5. handle the update event  ↴
bus.on('update', update)

// **** 7. also add the increment-x handler  ↴
bus.on('increment-x', ..)

var root = document.body.appendChild(document.createElement('div'))
update()

setInterval(function () {
  // **** 2. use the bus  ↴
  bus.emit('increment-n')
}, 1000)


function update () {
  html.update(root, html`<div> 
    <h1>${state.n}</h1>
    add the coaddunter display
    <div>${state.x}</div>
    <button onclick=${onclick}>CLICK ME</button>
  </div>`)
  function onclick (ev) {
    // **** 6. finally use incerment-x here  ↴
    bus.emit('increment-x')
  }
}

Now, he can start to move pieces of code other files (event handlers, etc.)

  //	****		reduce.js		****

module.exports = function (bus, state) { 

  bus.on('increment-n', function () {
    state.n++
    bus.emit('update')
  })
  bus.on('increment-x', ..)

 
}

The reducer

It's a common term in these architectures: The reducer listens for changes and modifies the state and emit additional state events.

Then use this in yo.js:

  //	****		yo.js		****

var html = require('yo-yo')
var state = {n : 5, x  0}

const EventEmitter = require('events')
var bus = new EventEmitter 
// **** 1. import our file  ↴
require('./reduce.js')(bus, state)

bus.on('update', update)

bus.on('increment-x', ..)

var root = document.body.appendChild(document.createElement('div'))
update()

setInterval(function () {
  bus.emit('increment-n')
}, 1000)


function update () {
  html.update(root, html`<div> 
    <h1>${state.n}</h1>
    add the coaddunter display
    <div>${state.x}</div>
    <button onclick=${onclick}>CLICK ME</button>
  </div>`)
  function onclick (ev) {
    // **** 2. just use emit and not bus  ↴
    // this will force you to only emit but not listen to events
    emit('increment-x')
  }
}

Note from above: You can just use an emit so that you're only emitting but never listening to events in you template so that data only flows in one direction. This is very close to the redux architecture.

In your template, you only do a minimum of data transformation (like making the input contents relatively clean).