Skip to content

Instantly share code, notes, and snippets.

@soska
Created November 24, 2017 17:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save soska/5cf05b2769a567b5b8bb342d34b1afab to your computer and use it in GitHub Desktop.
Save soska/5cf05b2769a567b5b8bb342d34b1afab to your computer and use it in GitHub Desktop.
An idea for a simple component-based state manager
import { Component } from 'react';
class Keeper extends Component{
static defaultProps = {
initialState:{},
stateRoot:'keeper',
reducer:state=>state,
serialize:null
}
constructor(props){
super(props);
this.state = {[props.stateRoot]: props.initialState};
}
__getState = ()=>{
return this.state[this.props.stateRoot]
}
__setState = (newState)=>{
this.setState({...this.state,[this.props.stateRoot]:newState},this.__serialize);
}
__serialize = ()=>{
if (typeof this.props.serialize === 'function') {
this.props.serialize(this.__getState());
}
}
__dispatch = action => this.__setState(this.props.reducer(this.__getState(), action));
render(){
return this.props.children(
this.__getState,
this.__dispatch
);
}
}
export default Keeper;
import React, { Component } from 'react';
import Keeper from './keeper';
import Storage from '../utils/storage';
import generateID from '../utils/id';
import {LocalDate} from 'js-joda';
import {STATUS_DONE, STATUS_PENDING} from '../utils/constants';
const createTodo = newTodo => ({
type:'NEW_TODO',
payload:{
id:generateID('todo'),
title:newTodo,
status:STATUS_PENDING,
meta:{}
}
});
const toggleDoneStatus = ({id}) => ({
type:'UPDATE_TODO_STATUS',
payload:{
id,
// status:STATUS_DONE
}
});
class TodosKeeper extends Component {
static defaultProps = {
listKey:LocalDate.now()
}
vault = new Storage('KEEPER::TODOS');
reducer = (state, action)=>{
if (action.type === 'NEW_TODO') {
return [...state, action.payload];
}
if (action.type === 'UPDATE_TODO_STATUS') {
const {id} = action.payload;
const index = state.findIndex(item => item.id === id );
const item = state[index];
const status = item.status === STATUS_DONE ? STATUS_PENDING : (STATUS_PENDING) ? STATUS_DONE : item.status;
if (item) {
return [
...state.slice(0,index),
{...item, status},
...state.slice(index+1),
];
}
}
return state;
}
// componentWillReceiveProps
getListKey = ()=>{
return this.props.listKey;
}
serialize = (todos) => {
this.vault.setItem(this.getListKey(),todos);
}
unserialize = initial => {
return this.vault.getItem(this.getListKey(), []);
}
render() {
window.TODO_KEEPER = this;
console.log('WTF',this.props);
// console.log(this.vault.unserialize());
return (
<Keeper initialState={this.unserialize([])} reducer={this.reducer} serialize={this.serialize} ref={ keeper => this.keeper = keeper }>
{(getState, dispatch)=>{
const onCreate = todo => dispatch(createTodo(todo));
const onToggleDoneStatus = todo => dispatch(toggleDoneStatus(todo));
// window.dispatch = dispatch;
return this.props.children({todos:getState(), onCreate, onToggleDoneStatus});
}}
</Keeper>
);
}
}
export default TodosKeeper;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment