block by fil 47678a37cc46fee9b3ed4769c31914e7

Redux + D3 in the browser

Full Screen

State management with redux and d3, in the browser thanks to unpkg.

index.html

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src="https://unpkg.com/redux@3.6.0/dist/redux.min.js"></script>
  
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
  </style>
</head>

<body>
  <script>
    // Feel free to change or delete any of the code you see in this editor!
    var svg = d3.select("body").append("svg")
      .attr("width", 360)
      .attr("height", 300)

    svg.append("text")
      .text("****")
      .attr("y", 100)
      .attr("x", 120)
      .style("font-size", 36)
      .style("font-family", "monospace")

    d3.select("body").append("button")
      .html('Reset')
      .on('click', () => store.dispatch({ type: 'RESET' }));

    d3.select("body").append("button")
      .html('Zero')
      .on('click', () => store.dispatch({ type: 'ZERO' }));

    
    const initialstate = { iteration: 0, counter: 0 };


function counter(_state = initialstate, action = null) {
  let state = snapshot(_state); // snapshot == clone
  switch (action.type) {
  case 'INCREMENT':
    state.iteration ++;
    state.counter ++;
    return state;
  case 'DECREMENT':
    state.iteration ++;
    state.counter --;
    return state;
  case 'ZERO':
    state.iteration ++;
    state.counter = 0;
    return state;
  case 'RESET':
    return initialstate;
  default:
    return _state;
  }
}

// Create a Redux store holding the state of your app. 
// Its API is { subscribe, dispatch, getState }. 
let store = Redux.createStore(counter);
 
// You can use subscribe() to update the UI in response to state changes. 
// Normally you'd use a view binding library (e.g. React Redux) rather than subscribe() directly. 
// However it can also be handy to persist the current state in the localStorage. 
 
store.subscribe(() => {
  var state = store.getState();
   svg.select("text")
      .text(`${state.iteration}: ${state.counter}`)
  }
);
 
// The only way to mutate the internal state is to dispatch an action. 
// The actions can be serialized, logged or stored and later replayed. 
d3.interval(() => {
   store.dispatch({ type: Math.random()>0.5 ?'INCREMENT' : 'DECREMENT' });
}, 100);




// deep cloning function excerpted from underscore.js
function snapshot (obj) {
  if(obj == null || typeof(obj) != 'object') {
    return obj;
  }
  var temp = new obj.constructor();
  for(var key in obj) {
    if (obj.hasOwnProperty(key)) {
      temp[key] = snapshot(obj[key]);
    }
  }
  return temp;
};    
    
  </script>
</body>