npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

iostore

v0.0.10

Published

[![NPM version](https://img.shields.io/npm/v/iostore.svg?style=flat)](https://npmjs.org/package/iostore) [![build status](https://img.shields.io/travis/yisbug/iostore.svg?style=flat-square)](https://travis-ci.org/yisbug/iostore) [![Test coverage](https://

Downloads

33

Readme

iostore

NPM version build status Test coverage Known Vulnerabilities David deps

背景介绍

由原 react-hooks-model 更名为 iostore

极简的全局数据管理方案,忘掉 reduxstatereduceractionobserver 这些复杂的概念吧。

特性

  • 总计只有 100 多行代码。
  • 只需要学会两个 API 即可使用,非常简单:createStore()useStore()
  • 像普通的 js 对象一样定义 store
  • 像普通的 js 对象一样使用数据和方法。
  • store 定义的方法内部可任意修改数据,可直接返回数据,支持同步、异步方法。
  • 当数据发生变化时,自动触发组件渲染。基于React Hooks API,实现了完整的单向数据流。
  • 集成异步方法的执行状态管理,目前最优雅的loading状态解决方案之一。
  • store 内部方法可以使用this.stores.TodoStore访问其他的 store 示例,实现更复杂的数据交互。

和之前的方案相比:

  • 不再区分 state, reducer, helper,去掉了这些概念,更简单。
  • 定义 store 就像定义一个普通的 js object 一样,只需要传入一个 namespace 用于区分不同的 store
  • 基于 Proxy 重新设计,数据变化,则自动通知组件,重新渲染。

TODO

  • [ ] TypeScript 支持
  • [ ] 支持 Vuejs
  • [ ] 更多的测试用例

如何使用

安装:

npm install iostore
// or
yarn add iostore

API

引入

import { createStore, useStore } from 'iostore';

createStore(params)

定义一个 store。参数:

普通的 js 对象,必须指定一个namespace

// TodoStore.js
import { createStore } from 'iostore';
createStore({
  namespace: 'TodoStore',
  todos: [],
  getTodoCount() {
    return this.todos.length;
  },
  getNs() {
    return this.namespace;
  },
  ...rest, // 其余自定义的数据和方法
});

// UserStore.js
import { createStore } from 'iostore';
createStore({
  namespace: 'UserStore',
  // 访问其他 store 的方法。
  getTodoCount() {
    return this.stores.TodoStore.getTodoCount();
  },
  ...rest, // 其余自定义的数据和方法
});

useStore()

React 函数式组件中引入所需 store。 无参数。 得益于 ES6 中的解构赋值语法,我们从该方法的返回值中,单独声明所需的 store。

框架会在 store 中注入 stores 对象,用来访问其他 store 的数据。 一般来说,只推荐访问其他 store 的计算数据,不要访问其他 store 中可能导致修改数据的方法。 如果需要修改其他 store 的数据,请在逻辑层/组件内处理。

如下:

const Todo = () => {
  const { TodoStore } = useStore();
  // 之后便可以自由的使用 TodoStore 中定义的方法了。
  const ns = TodoStore.getNs();
  return <div>{ns}</div>;
};

关于 loading

在对交互要求较高的场景下,获取异步方法的执行状态是非常必要的。

例如显示一个 loading 页面告诉用户正在加载数据,按钮上显示一个loading样式提示用户该按钮已经被点击。

当你使用iostore时,这一切变得非常简单。

我们可以非常容易的获取到每一个异步方法的loading状态,甚至可以获取到一个store下有没有异步方法正在执行。

  • 获取store中有没有异步方法正在执行:Store.loading,返回 true/false
  • 获取store中某个异步方法的 loading 状态:Store.asyncFunction.loading,返回 true/false

示例如下:

// 定义 store
createStore({
  namespace: 'TodoStore',
  id: 0,
  async inc() {
    await sleep(1000 * 5);
    this.id++;
  },
});

// 获取 loading 状态
const Todo = () => {
  const { TodoStore } = useStore();
  const handleClick = () => TodoStore.inc();
  // TodoStore.loading  store 级别的 loading 状态
  // TodoStore.inc.loading 某个异步方法的 loading 状态
  return (
    <button loading={TodoStore.inc.loading} onClick={handleClick}>
      submit
    </button>
  );
};

完整的 Todo 示例

// TodoStore.js
import store, { createStore, useStore } from 'iostore';
export default createStore({
  namespace: 'TodoStore', // store 命名空间
  id: 0,
  todos: [
    {
      id: 0,
      content: 'first',
      status: 'DOING',
    },
  ],
  addTodo(content) {
    this.id++;
    const todo = {
      id: this.id,
      content,
      status: 'DOING',
    };
    this.todos.push(todo);
  },
  getTodoById(id) {
    return this.todos.filter(item => item.id === id)[0];
  },
  updateTodo(id, status) {
    const todo = this.getTodoById(id);
    if (!todo) return;
    todo.status = status;
  },
  // test async function
  incId: 0,
  async delayIncId() {
    await sleep(1000 * 3);
    this.incId++;
  },
});

// Todos.js
import React, { useRef } from 'react';
import store, { createStore, useStore } from '../src/index';
import todoStore from './TodoStore';

export default () => {
  /**
   * 获取 TodoStore 的几种方式:
   * const { TodoStore } = useStore(); // 更符合 React Hooks 的理念
   * const { TodoStore } = store;
   * const TodoStore = todoStore.useStore();
   */
  const { TodoStore } = useStore();
  const inputEl = useRef(null);
  const handleClick = item => {
    if (item.status === 'DOING') {
      TodoStore.updateTodo(item.id, 'COMPLETED');
    } else if (item.status === 'COMPLETED') {
      TodoStore.updateTodo(item.id, 'DOING');
    }
  };
  const handleAddTodo = () => {
    console.warn('set data within component, should be got console.error : ');
    TodoStore.todos[0].id = 1000;
    const text = inputEl.current.value;
    if (text) {
      TodoStore.addTodo(text);
    }
  };
  console.log('render', 'totos.length:' + TodoStore.todos.length);
  return (
    <div>
      <div data-testid="incid">{TodoStore.incId}</div>
      {!TodoStore.delayIncId.loading ? <div data-testid="incidfinish" /> : ''}

      <div data-testid="incidloading">{TodoStore.delayIncId.loading ? 'loading' : 'completed'}</div>
      <div data-testid="todocount">{TodoStore.todos.length}</div>
      <ul data-testid="todolist">
        {TodoStore.todos.map(item => {
          return (
            <li onClick={() => handleClick(item)} key={item.id}>
              {item.content}
              <span>{item.status}</span>
            </li>
          );
        })}
      </ul>
      <input ref={inputEl} data-testid="todoinput" type="text" />
      <button data-testid="todobtn" onClick={() => handleAddTodo()}>
        add todo
      </button>

      <button data-testid="incbtn" onClick={() => TodoStore.delayIncId()}>
        delay inc id
      </button>
    </div>
  );
};

License

MIT