# react-kiss **Repository Path**: mirrors_ecomfe/react-kiss ## Basic Information - **Project Name**: react-kiss - **Description**: A simple and stupid react container solution - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-08-08 - **Last Updated**: 2026-01-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # react-kiss [Redux](https://redux.js.org/) and [mobx-state-tree](https://github.com/mobxjs/mobx-state-tree) are both good state container solutions, however they introduces too many terminologies and bioperlates to structure a simple app. We want something super simple and stupid, something that can define a state container everywhere at any granularity and combine them together to form a complete app. react-kiss is thus a state container which: - introduces minimal efforts to create and use states. - ships with both state and state transfer definitions, handles sync and async workflows naturally. - allows split states to different parts as small as possible and combine then together when required. - encourages establishing and joining state container in a smaller scope instead of a monotonous global state. ## Install ```shell npm install react-kiss ``` ## Region A region is a container of a state and some workflows to manipulate state in the context of a given payload. ### State A state is a predefined structure and its current data, any plain object can be a state. ### Workflow A workflow is a process which receives a payload and manipulates current state, a workflow can manipulates state either synchronously or asychronously, it is also possible manipulates state multiple times within a workflow. There are 2 forms of workflows. #### Simple workflow A simple workflow is a simple function that receives a payload and current state, it should return either a state patch like: ```javascript const setCurrentUser = (user, state) => { if (state.currentUser) { return {}; } return { currentUser: user }; }; ``` or a state updater function like: ```javascript const addValue = (amount, state) => { if (state.value >= 100) { return {}; } return ({value}) => ({value: value + amount}); }; ``` #### Composite workflow A composite workflow is a workflow which may manipulates state multiple times or involves async process, it is defined as a generator function: ```javascript function* saveTodo(todo) { yield {submitting: true}; try { const newTodo = yield postTodo(todo); yield state => { const {todos} = state; return { todos: [...todos, newTodo], submitting: false }; }; } catch (ex) { yield {submitting: false, error: ex}; } }; ``` This generator function receives `(payload, getState)` as its arguments, and yields value in 3 types: - a simple object is treated as a state patch. - a function is treated as a state updater. - a `Promise` instance is treated as an async process, its resolved value or rejected error will returned back to `yield` expression. ### Selector A selector is a pure function which computes and selects certain values from current state, selectors are defined as an object with function values: ```javascript const selectors = { filterVisibleTodos({todos, filter}) { return filter ? todos.filter(todo => todo.includes(filter)) : todos; } }; ``` Selectors can also receive arbitary arguments, the first argument is always the `currentState`, rest arguments are those passed to selector on invocation. When invoke a selector, the `currentState` argument is omitted (it is bound automatically), so the above selector is called just as `const todos = filterVisibleTodos()`; ## Define a region To define a region, we just need to provide an `initialState` and a map of `workflows` to `defineRegion` exported function: ```javascript import {defineRegion} from 'react-kiss'; const initialState = { todos: [ 'Buy milk', 'Meet John at peace park' ], filter: '', error: null, submitting: false }; const workflows = { * saveTodo(todo) { yield {submitting: true}; try { const newTodo = yield postTodo(todo); yield state => { const {todos} = state; return { todos: [...todos, newTodo], submitting: false }; }; } catch (ex) { yield {submitting: false, error: ex}; } }, filterByKeyword(keyword) { return {filter: keyword}; } }; const selectors = { filterVisibleTodos({todos, filter}) { return filter ? todos.filter(todo => todo.includes(filter)) : todos; } }; const todoRegion = defineRegion(initialState, workflows, selectors); export const establishTodo = todoRegion.establish; export const joinTodo = todoRegion.join; ``` The return value of `defineRegion` function is an object containing `establish` and `join` function. ## Establish a region By `defineRegion` we get a region definition but it is not yet usable as a state container, we should establish it at a parent scope and join it from it's children. To establish a region, call `establish` function returned by `defineRegion` like an HOC: ```jsx import {establishTodo} from 'regions'; const Todo = () => (
{message} @ {username}
}