Learn about our RFC process, Open RFC meetings & more.Join in the discussion! »

srimmer

0.6.0 • Public • Published

Srimmer

Srimmer provides simple api to use react, immer and TypeScript.

inspired react-copy-write.

API

import { define, Select } from "srimmer";
 
/**
 * Extract consumer's selected state. `Select<typeof Consumer>`
 */
export { Select };
 
/**
 * Your state.
 */
type State = {
  todos: {
    name: string;
    status: string;
  }[];
};
 
/**
 * Define some state utilities from your state type.
 */
const defined = define<State>();
 
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 {<T>(select: (state: State) => T) => Consumer<T>}
   */
  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)

import { define, Select } from 'srimmer';
 
export type State = { ... };
 
export const {
  Provider,
  select,
  update,
  patches,
  get,
  set
} = define<State>();
 
export { Select };

define your action (src/action/index.ts)

import { update } from "../../state";
 
export const addNewTask = () => {
  update(state => {
    state.todos.push({
      name: `new todo ${state.todos.length}`,
      status: "todo"
    });
  });
};

bootstrap (src/index.tsx)

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "./state";
 
ReactDOM.render(
  <Provider state={createInitialState()}>
    <App />
  </Provider>,
  document.getElementById("app")!
);
 
function createInitialState() {
  return JSON.stringify(document.getElementById("app")!.getAttribute("data"));
}

consume state (src/component/*/.tsx)

import { select, Select } from '../../state';
import { addNewTask } from '../action';
 
const Consumer = select(state => ({
  todos: state.todos
}));
 
export default () => (
  <Consumer>
    {state => (
      <button onClick={() => onAddButtonClick(state)}>add</button>
      <div>{todos(state)}</div>
    )}
  </Consumer>
);
 
const todos = (state: Select<typeof Consumer>) => {
  return state.todos.map(todo => (
    <div key={todo.id}>{todo.name} - {todo.status}</div>
  ));
}
 
const onAddButtonClick = () => {
  addNewTask();
};

testing your updater (test/action/index.test.ts)

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

/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.

Keywords

Install

npm i srimmer

DownloadsWeekly Downloads

4

Version

0.6.0

License

MIT

Unpacked Size

39 kB

Total Files

28

Last publish

Collaborators

  • avatar