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:
- Decide whether you want a global or local store.
- Define the properties you want to put into state
- Define any methods (like getting data from an API or updating a canvas.)
- 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