Wonderland Labs Presents
Looking Glass Engine 3.1

Getting Started

Looking Glass Engine is system-agnostic; at the moment there is no singular method of designing, organizing, and binding to State systems.

The basic flow of State design in LGE is:

  1. Decide whether you want a global or local store.
  2. Define the properties you want to put into state
  3. Define any methods (like getting data from an API or updating a canvas.)
  4. Synchronize the Store's values with the view layer

Installation

LGE is a module intended to be used in a babelized context. It has been tested/used in React, and its unit tests run in tap/node.

yarn add @wonderlandlabs/looking-glass-engine
--------
import {ValueStream} from '@wonderlandlabs/looking-glass-engine';
const myStore = new ValueStream('counter')
.property('count', 0, 'integer');

The TODO MVC app as a ValueStream

The TODO MVC app is easily ported into a store:

import {ValueStream} from '@wonderlandlabs/looking-glass-engine';
  import uuid from 'uuid/v4';
  console.log('uuid:', uuid);
  class Todo {
    constructor(text, id, completed) {
    this.id = id || uuid()
    this.text = text;
    this.completed = completed;
  }
  clone() {
    return new Todo(this.text, this.id, this.completed)
  }
}
  export default new ValueStream('todos')
  .property('todos', [new Todo('React With LGE')], 'array')
  .method('addTodo', (s, text) => {
  s.do.setTodos([...s.my.todos, new Todo(text) ])
})
  .method('deleteTodo', (s, id) => {
  s.do.setTodos(s.my.todos.filter(todo => todo.id !== id));
})
  .method('completeTodo', (s, id) => {
  console.log('completing todo ', id );
  s.do.setTodos(s.my.todos.map((todo) => {
  if (todo.id === id) {
  let newTodo = todo.clone();
  newTodo.completed = !newTodo.completed;
  return newTodo;
}
  return todo;
}));
})
  .method('completeAll', (s) => {
  s.do.completeForAll(true);
})
  .method('clearCompleted', (s) => {
  s.do.completeForAll(false);
})
  .method('completeForAll', (s, complete) => {
  s.do.setTodos(s.my.todos.map((todo) => {
    if (todo.completed !== complete) {
      let newTodo = todo.clone();
      newTodo.completed = complete;
      return newTodo;
    }
    return todo;
  }));
})
  .method('editTodo', (s, id, text) => {
  s.do.setTodos(s.my.todos.map((todo) => {
    if (todo.id === id) {
      let newTodo = todo.clone();
      newTodo.text = text;
      return newTodo;
    }
    return todo;
  }));
});

The binding to the App:

import React, {Component} from 'react'
import Header from './Header'
import MainSection from './MainSection'
import todoState from './todo.state';
class App extends Component {
constructor(props) {
  super(props);
  this.state = {...todoState.value};
}
componentWillUnmount() {
  this.mounted = false;
  this._sub.unsubscribe();
}
componentDidMount() {
  this.mounted = true;
  this._sub = todoState.subscribe((s) => {
    if (this.mounted) {
      this.setState(s.value)
    }
  }, (e) => {
    console.log('state error: ', e);
  })
}
render() {
  return (
    <div>
      <Header addTodo={todoState.do.addTodo}/>
      <MainSection todos={this.state.todos} actions={todoState.do}/>
    </div>
  )
}
}
export default App

The full codeSandbox can be found HERE

More Examples