1.0.0-beta-3 • Published 6 years ago

@ice/store v1.0.0-beta-3

Weekly downloads
131
License
MIT
Repository
github
Last release
6 years ago

English | 简体中文

icestore

Lightweight React state management library based on react hooks

NPM version Package Quality build status Test coverage NPM downloads Known Vulnerabilities David deps

Installation

icestore requires React 16.8.0 or later.

npm install @ice/store --save

Introduction

icestore is a lightweight React state management library based on hooks. It has the following core features:

  • Minimal & Familiar API: No additional learning costs, easy to get started with the knowledge of React Hooks.
  • Class Component Support: Make old projects enjoying the fun of lightweight state management with friendly compatibility strategy.
  • Built in Async Status: Records loading and error status of async actions, simplifying the rendering logic in the view layer.
  • TypeScript Support: Provide complete type definitions to support intelliSense in VS Code.

Getting Started

Let's build a simple todo app from scatch using icestore which includes following steps:

Step 1 - Use a model to define your store:

export const todos = {
  state: {
    dataSource: [],
  },
  actions: {
    async fetch(prevState, actions) {
      await delay(1000);
      const dataSource = [
        { name: 'react' },
        { name: 'vue', done: true},
        { name: 'angular' },
      ];
      return {
        ...prevState,
        dataSource,
      }
    },
    add(prevState, todo) {
      return {
        ...prevState,
        dataSource: [
          ...prevState.dataSource,
          todo,
        ]
      };
    },
  },
};

Step 2 - Create the store

import { createStore } from '@ice/store';
import * as models from './models';

export default createStore(models);

Step 3 - Wrap your application

import React from 'react';
import ReactDOM from 'react-dom';
import store from './store';

const { Provider } = store;

ReactDOM.render(
  <Provider>
    <App />
  </Provider>,
  rootEl
); 

Step 4 - Consume model

import React, { useEffect } from 'react';
import store from './store';

const { useModel } = store;

function Todos() {
  const [ state, actions ] = useModel('todos');
  const { dataSource } = state;
  const { fetch, add } = actions;

  useEffect(() => {
    fetch();
  }, []);

  function handleAdd(name) {
    add({ name });
  }

  return (
    <div>
      <ul>
        {dataSource.map(({ name, done }, index) => (
          <li key={index}>
            <label>
              <input
                type="checkbox"
                checked={done}
                onClick={() => onCheck(index)}
              />
              {done ? <s>{name}</s> : <span>{name}</span>}
            </label>
            <button onClick={() => onRemove(index)}>-</button>
          </li>
        ))}
      </ul>
      <div>
        <input
          onKeyDown={event => {
            if (event.keyCode === 13) {
              handleAdd(event.target.value);
              event.target.value = '';
            }
          }}
          placeholder="Press Enter"
        />
      </div>
    </div>
  );
}

API

createStore

createStore(models)

The function called to create a store.

import { createStore } from '@ice/store';
const store = createStore(models);
const { Provider, useModel, withModel } = store;

Parameters

models

import { createStore } from '@ice/store'

const counterModel = {
  state: {
    value: 0
  },
};

const models = {
  counter: counterModel
};

createStore(models)

state

state: any: Required

The initial state of the model.

const example = {
  state: { loading: false },
};

actions

actions: { [string]: (prevState, payload, actions, globalActions) => any }

An object of functions that change the model's state. These functions take the model's previous state and a payload, and return the model's next state.

const counter = {
  actions: {
    add: (prevState, payload) => prevState + payload,
  }
};

Actions provide a simple way of handling async actions when used with async/await:

const counter = {
  actions: {
    async addAsync(prevState, payload) => {
      await delay(1000);
      return prevState + payload;
    },
  }
};

You can call another action by useing actions or globalActions:

const user = {
  state: {
    foo: [],
  }
  actions: {
    like(prevState, payload, actions, globalActions) => {
      actions.foo(payload); // call user's actions
      globalActions.user.foo(payload); // call actions of another model
      
      // do something...

      return {
        ...prevState,
      };
    },
    foo(prevState, id) {
      // do something...

      return {
        ...prevState,
      };
    },
  }
};

Return

Provider

Provider(props: { children, initialStates })

Exposes the store to your React application, so that your components will be able to consume and interact with the store via the hooks.

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from '@ice/store';

const { Provider } = createStore(models);
ReactDOM.render(
  <Provider>
    <App />
  </Provider>,
  rootEl
); 

useModel

useModel(name: string): [ state, actions ]

A hook granting your components access to the model instance.

const counter = {
  state: {
    value: 0
  },
  actions: {
    add: (prevState, payload) => ({...prevState, value: prevState.value + payload}),
  }
};

const { userModel } = createStore({ counter });

functio FunctionComponent() {
  const [ state, actions ] = userModel('name');

  state.value; // 0

  actions.add(1); // state.value === 1
}

useModelActions

useModelActions(name: string): actions

A hook granting your components access to the model actions.

functio FunctionComponent() {
  const actions = useModelActions('name');
  actions.add(1);
}

useModelActionsState

useModelActionsState(name: string): { [actionName: string]: { isLoading: boolean, error: Error } }

A hook granting your components access to the action state of the model.

functio FunctionComponent() {
  const actions = useModelActions('name');
  const actionsState = useModelActionsState('name');

  useEffect(() => {
    actions.fetch();
  }, []);

  actionsState.fetch.isLoading;
  actionsState.fetch.error;
}

withModel

withModel(name: string, mapModelToProps?: (model: [state, actions]) => Object = (model) => ({ [name]: model }) ): (React.Component) => React.Component

Use withmodel to connect the model and class component:

class TodoList extends Component {
  render() {
    const { counter } = this.props;
    const [ state, actions ] = counter;
    const { dataSource } = state;
    
    state.value; // 0

    actions.add(1);
  }
} 

export default withModel('counter')(TodoList);

Browser Compatibility

ChromeFirefoxEdgeIESafariOperaUC
9+ ✔

Inspiration

icestore refines and builds upon the ideas of constate & rematch.

Contributors

Feel free to report any questions as an issue, we'd love to have your helping hand on icestore.

If you're interested in icestore, see CONTRIBUTING.md for more information to learn how to get started.

License

MIT

2.0.4

3 years ago

2.0.3

4 years ago

2.0.2

4 years ago

2.0.1

4 years ago

2.0.0

4 years ago

2.0.0-4

4 years ago

2.0.0-3

4 years ago

2.0.0-2

4 years ago

2.0.0-0

5 years ago

1.4.3

5 years ago

1.4.3-6

5 years ago

1.4.3-5

5 years ago

1.4.3-2

5 years ago

1.4.3-1

5 years ago

1.4.3-4

5 years ago

1.4.3-3

5 years ago

1.4.3-0

5 years ago

1.4.2

6 years ago

1.4.1

6 years ago

1.4.1-beta-0

6 years ago

1.4.0

6 years ago

1.4.0-beta-1

6 years ago

1.4.0-beta-0

6 years ago

1.3.5

6 years ago

1.3.4

6 years ago

1.3.3

6 years ago

1.3.2

6 years ago

1.3.2-beta-0

6 years ago

1.3.0-beta-3

6 years ago

1.3.0-beta-4

6 years ago

1.3.0-beta-5

6 years ago

1.3.1

6 years ago

1.3.0

6 years ago

1.3.0-beta-2

6 years ago

1.3.0-beta-0

6 years ago

1.3.0-beta-1

6 years ago

1.2.0

6 years ago

1.1.2

6 years ago

1.1.1

6 years ago

1.1.0

6 years ago

1.1.0-beta-0

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago

1.0.0-beta-3

6 years ago

1.0.0-beta.2

6 years ago

1.0.0-beta.0

6 years ago

0.4.7

6 years ago

0.4.6

6 years ago

0.4.5

6 years ago

0.4.4

6 years ago

0.4.3

6 years ago

0.4.2

6 years ago

0.4.1

6 years ago

0.4.0

6 years ago

0.4.0-alpha.2

6 years ago

0.4.0-alpha.1

6 years ago

0.3.0

7 years ago

0.2.4

7 years ago

0.1.6

7 years ago

0.2.2

7 years ago

0.2.1

7 years ago

0.2.0

7 years ago

0.1.5

7 years ago

0.1.4

7 years ago

0.1.1

7 years ago

0.1.0

7 years ago