https://github.com/hrsh7th/srimmer
Srimmer provides simple api to use react and immer.
https://github.com/hrsh7th/srimmer
context-api immer react state-management
Last synced: about 2 months ago
JSON representation
Srimmer provides simple api to use react and immer.
- Host: GitHub
- URL: https://github.com/hrsh7th/srimmer
- Owner: hrsh7th
- Created: 2018-10-06T14:58:57.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2018-10-25T18:07:49.000Z (almost 7 years ago)
- Last Synced: 2024-05-01T20:20:50.875Z (over 1 year ago)
- Topics: context-api, immer, react, state-management
- Language: TypeScript
- Size: 35.2 KB
- Stars: 6
- Watchers: 4
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Srimmer
Srimmer provides simple api to use react, immer and TypeScript.
inspired `react-copy-write`.
# API
```typescript
import { define, Select } from "srimmer";/**
* Extract consumer's selected state. `Select`
*/
export { Select };/**
* Your state.
*/
type State = {
todos: {
name: string;
status: string;
}[];
};/**
* Define some state utilities from your state type.
*/
const defined = define();export const {
/**
* State provider.
* @type {React.ComponentType<{ state: State; }>}
*/
Provider,/**
* State updater.
* @type {(updater: (state: State) => void) => void}
*/
update,/**
* immer's patchListener.
* @type {(patchListener: PatchListener) => void}
*/
patches,/**
* State selector.
* @type {(select: (state: State) => T) => Consumer}
*/
select,/**
* State getter.
* Note: Carefully. It makes implicit depends to state values.
* @type {() => State}
*/
get,/**
* State setter.
* Note: For testing.
* @type {(state: State) => void}
*/
set
} = defined;
```# Real World Usage
## define your state (src/state/index.ts)
```typescript
import { define, Select } from 'srimmer';export type State = { ... };
export const {
Provider,
select,
update,
patches,
get,
set
} = define();export { Select };
```## define your action (src/action/index.ts)
```typescript
import { update } from "../../state";export const addNewTask = () => {
update(state => {
state.todos.push({
name: `new todo ${state.todos.length}`,
status: "todo"
});
});
};
```## bootstrap (src/index.tsx)
```typescript
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "./state";ReactDOM.render(
,
document.getElementById("app")!
);function createInitialState() {
return JSON.stringify(document.getElementById("app")!.getAttribute("data"));
}
```## consume state (src/component/\*_/_.tsx)
```typescript
import { select, Select } from '../../state';
import { addNewTask } from '../action';const Consumer = select(state => ({
todos: state.todos
}));export default () => (
{state => (
onAddButtonClick(state)}>add
{todos(state)}
)}
);const todos = (state: Select) => {
return state.todos.map(todo => (
{todo.name} - {todo.status}
));
}const onAddButtonClick = () => {
addNewTask();
};
```## testing your updater (test/action/index.test.ts)
```typescript
import diff from 'snapshot-diff'; # https://github.com/jest-community/snapshot-diff
import { set, get } from '../../../src/state';
import { addNewTask } from '../../../src/action';beforeEach(() => {
set({ ...fixture });
});test('addNewTask', () => {
const state = get()!;
addNewTask();
expect(diff(state, get()!)).toMatchSnapshot();
});
```# Recommended Structure
```bash
/src
/state # State schemas and querying utility functions.
index.ts
/action # State updators.
index.ts
/component # State selectors.
index.tsx
index.tsx # Bootstrap.
```See `hrsh7th/ganttcharty`.