My state manager for React, Preact, Inferno

I love reinventing bicycles and other useful items. It doesn't always work out well, but the process is interesting. I bring to your attention the state management library for React, Preact (weight only 4.8Kb). The library is still under development, but you can already try it.





Let's start with an example of everyone's favorite TODO organizer. Source code on github . First, let's create the main component main.js.





// main.js
import React, { createElement, Component, createContext } from 'react';
import ReactDOM from 'react-dom';
import {Connect, Provider} from './store'
import Input from './InputComp'
import TodoList from './TodoList'
import LoadingComp from './LoadingComp'

const Main = () => (
  <Provider>
    <h1>Todo:</h1>
    <LoadingComp>
      <TodoList/>
    </LoadingComp>
    <hr/>
    <Input/>
  </Provider>
)

ReactDOM.render(<Main />, document.getElementById("app"));
      
      



Further side. We need the store to initialize the library, and here we also specify all the necessary files with actions. In our example, these are actions.js and actionsSetup.js





// store.js

import React, { createElement, Component, createContext } from 'react';
import createStoreFactory from 'redoor';

//     actions.js  actionsSetup.js
import * as actions from './actions'
import * as actionsSetup from './actionsSetup'

//       React
const createStore = createStoreFactory({
  Component, 
  createContext, 
  createElement
});

//         
//    
const { Provider, Connect } = createStore([
  actions,
  actionsSetup
]);

export { Provider, Connect };
      
      







// actions.js

//         
// redoor     
// initState       ,
//   ,     
export const initState = {
    todos:[],
    value:'',
}

//     
//  state -   
//  args -      
//     
export const a_enter = ({state,args}) => {
  let {value,todos} = state;
  todos.push({
    id:(Math.random()+"").substr(2),
    value:value,
    done:false
  });
  return {
    value:'',
    todos
  }
}

//    
export const a_done = ({state,args}) => {
  let {todos} = state;
  let id = args.id;
  todos = todos.map(it=>(it.id === id ? (it.done = !it.done, it) : it))
  return {
    todos
  }
}

//    
export const a_delete = ({state,args}) => {
  let {todos} = state;
  let id = args.id;
  todos = todos.filter(it=>it.id !== id)
  return {
    todos
  }
}
      
      







// InputComp.js
import React from 'react';
import {Connect} from './store'

// redoor     cxRun   
//  
const Input = ({cxRun, value})=><label className="input">
  Todo:
  
  //        
  <input onChange={e=>cxRun({value:e.target.value})} 
					value={value} 
					type="text" 
  />
  
  //     a_enter   actions.js
  <button onClick={e=>cxRun('a_enter')} disabled={!value.length}>
		ok
	</button>
</label>

//   redoor     
export default Connect(Input);
      
      



cxRun . , actions.js.





.





// TodoList.js
import React from 'react';
import {Connect} from './store'

const Item = ({cxRun, it, v})=><div className="item">
  //   a_done,      
  //         args
  <div className="item_txt" onClick={e=>cxRun('a_done',it)}>
    {v+1}) {it.done ? <s>{it.value}</s> : <b>{it.value}</b>}
  </div>
  <div className="item_del" onClick={e=>cxRun('a_delete',it)}>
    &times;
  </div>
</div>

const TodoList = ({cxRun, todos})=><div className="todos">
  {
    todos.map((it,v)=><Item key={v} cxRun={cxRun} it={it} v={v}/>)
  }
</div>

export default Connect(TodoList);
      
      



. value todos. initState actions.js. initState , . , .





-- "_" "action". cxRun. state args.





state --





args -- cxRun. cxRun('a_delete', it), , args.





, .





? setState actions.js bindStateMethods.





//actions.js
let __setState;
let __getState;

//     
export const bindStateMethods = (getState, setState) => {
  __getState = getState;
  __setState = setState;
};

export const a_setup = async ({state,args}) => {
  __setState({loading:true});
  let data = await loading();
  __setState({
    loading:false,
    todos:data
  })
}
      
      



"a_load", , . , __getState .





Debugger

redoor-devtool. redoor localhost:8333. , . .





redoor-devtool:





yarn add redoor-devtool
      
      







npx redoor-devtool -o
      
      



the "-o" key will open chrome at http: // localhost: 8333 , where the debugger will be.





Conclusion

On my own behalf, I can share that I have already done several projects using this library. It was quite convenient to work with it in a project with sockets. There are, of course, features of use. For example, remember that all actions are "visible" from all modules. This won't be a problem if you have a clear structure for naming your actions. In my projects I use this naming "a_moduleName_actionName".





That's all for now. If there is interest - I will try to write a more detailed review.








All Articles