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

extore

v0.2.2

Published

This lib helps you manage your application state in a flux way through React's Context API.

Downloads

2

Readme

extore

This lib helps you manage your application state in a flux way through React's Context API.

createStore(state: any, actions: object) => Component

By passing a default state object and a list of actions to the createStore() function, you will create a new component with its own context. It will expose its state along with the actions you specified so that every consumer of its context may be able to read and update the current state.

Once the store is built, it will initialize the state with the value you specified, then will add every actions inside as well. To make writing your actions easier, all of them will be bound to the store's state when they are called. This means you'll have internal access to the state using this and that you can access other actions from your actions easily, as they're technically part of the store's state.

In order to still be able to modify the state, a proxy to the setState function is also put in the state so that you can call it from your actions using this.setState as you would usually do.

Beware though not to have any collision between your actual state object keys and the name of your actions. At setup, actions will overwrite any piece of state that have the same name and later, when you use setState, you might also replace your actions with simple values.

const state = {
  counter: 0,
}

const actions = {
  changeCounter(change) {
    // access the store's state content directly through this
    const counter = this.counter + change

    // modify the state with this.setState
    this.setState({ counter })
  }

  increment() {
    // access the other actions with this
    this.changeCounter(+1)
  }

  decrement() {
    this.changeCounter(-1)
  }
}

const Store = createStore(state, actions)

// wrap your app with it to make it a global context
// but remember you can also put it anywhere else in the tree for more detailed scoping
ReactDOM.render(<Store><App /></Store>, root)

connect(stores: object, selector: function) => (component: Component) => Component

Now that your Store is ready, you'll want to connect some components to it in order to consume the context. To do so, pass an object to the connect function listing the stores you'll want to connect to.

The connect function is a helper that will combine different Context Consumers for each store mentionned and pass their state as props.

The connected component will receive props matching the object you gave, meaning for each key you defined in this object, one prop will be created, containing the state and actions of the corresponding store.

You can also pass an optional selector as 2nd parameter, it will read all the props that the component receives, including the consumed context. The object it returns will be the only props passed to the connected component.

import AuthStore from '../stores/auth'
import FilesStore from '../stores/files'

// auth store:
// - state: { user: object | null }

// files store:
// - state: { list: [{ id: number, name: string }]}
// - actions: { delete(id: string) }

const FileList = ({ isAuthenticated, files }) => {
  if (!isAuthenticated) {
    return null
  }

  return (
    <ul>
      {files.list.map(file => (
        <li key={file.id}>
          <span>{file.name}</span>
          <button onClick={() => files.delete(file.id)}>x</button>
        </li>
      ))}
    </ul>
  )
}

function selector({ auth, files }) {
  return { isAuthenticated: Boolean(auth.user), files }
}

export default connect({ auth: AuthStore, files: FileStore }, selector)(FileList)

combineStores(...stores: [Component]) => Component

If you do not want to manually add all the stores in your app, you can generate a wrapper component that will render them for you in one place. For that you need to pass a series of Stores to the combineStores function and it will return you the wrapper component.

import AuthStore from '../stores/auth'
import FilesStore from '../stores/files'

const GlobalStore = combineStores(AuthStore, FilesStore)

// the GlobalStore will render both the auth and files store around the App
render(<GlobalStore><App /></GlobalStore>, root)