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

smox

v2.5.5

Published

Fast 1kB state management that path-updating.

Downloads

24

Readme

Use

npm i smox -S
import { Smox } from 'smox'

const state = {
  count: 0,
}

const actions = {
  up(state) {
    state.count++
  },
  down(state) {
    state.count--
  },
}

const effects = {
  async upAsync(actions) {
    await new Promise(t => setTimeout(t, 1000))
    actions.up()
  },
}

const store = new Smox({ state, actions, effects })

以上,smox 的部分就结束啦,创建了一个 store

React

对外暴露 Provider 和 Consumer 组件,可以方便的用于 react 组件中

为什么使用 render props 而不是 HOC?由于 hooks API 的出现,导致 HOC 只适用于 class API,render props 可同时适用于 class 和 function,是最合适的拓展机制

其中,Provider 组件接受 store 作为参数,而 Consumer 可以接受到 path 限定过的 part store

import { Provider, Consumer } from 'smox'

class App extends React.Component {
  render() {
    return (
      <>
        <Consumer>
          {({ state, actions, effects }) => (
            <>
              <h1>{state.count}</h1>
              <button onClick={actions.up}>+</button>
              <button onClick={actions.down}>-</button>
              <button onClick={effects.upAsync}>x</button>
            </>
          )}
        </Consumer>
      </>
    )
  }
}

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

Path

path 是一个匹配机制,举例说明:

const state = {
  counter: {
    count: 0,
  },
}

const actions = {
  counter: {
    up(state, data) {
      //此处的 state 为同路径的 { count:0 }
      state.count += data
    },
    down(state, data) {
      state.count -= data
    },
  },
}

const effects = {
  counter: {
    async upAsync(actions) {
      //此处的 actions 为同路径的 { up(), down() }
      await new Promise(t => setTimeout(t, 1000))
      actions.up()
    },
  },
}

可以看到,跟对象下面的 counter 对象,此时的 path 是 /counter

现在我们有个 <App /> 跟组件,它默认匹配全局的 store,此时它的 path 是 /

然后 <App /> 有个子组件 <Counter />,这个组件的 path 是 /counter,那么它匹配的就是 store 对象下面的 counter 对象的属性和方法

function App() {
  //跟组件匹配的是全局 store
  return <Counter />
}

function Counter() {
  return (
    <Consumer>
      {({ state, actions, effects }) => ( 
        /*此处是 counter 对象中的 
        { state:{ count }, 
          actions:{ up(), down() }, 
          effects:{ asyncUp() } 
        }*/
        <>
          <h1>{state.count}</h1>
          <button onClick={actions.up}>+</button>
          <button onClick={actions.down}>-</button>
          <button onClick={effects.upAsync}>x</button>
        </>
      )}
    </Consumer>
  )
}

通过这个约定,我们不需要关心 store 的拆分,只需要按照规定安排 store 和 组件即可

Proxy、async/await

Proxy、async/await 可以使得 actions 代码同步,更好看

const actions = {
  up(state) {
    state.count += 1
    state.count += 2
  },
}

使用这个 polyfill 可以兼容 ie9+

同时 effects 下面,配合 async/await,也能同步的编写逻辑

const effects = {
  async upAsync(actions) {
    await new Promise(t => setTimeout(t, 1000))
    actions.up()
    actions.down()
  },
}

Immed

immed 是 smox 内部的一个子包,它和 immer 类似,但是和 path 结合使用,性能更好

import { produce } from 'smox'

class App extends React.Component {
  onClick = () => {
    this.setState(
      produce(this.state, draft => {
        draft.count++
      })
    )
  }
}

export default App

Demo

License

MIT