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

medux

v1.2.0

Published

Medux: Modular immutable state management

Downloads

76

Readme

Medux: Modular immutable state management

Manage state and actions using immer

Getting Started

yarn add medux

Store

import { createStore } from 'medux'

const storeProps = {

  createState: () => ({
    count: 0
  }),
  
  actions: {
    increment(num = 1) {

      // `this` has getState, setState, actions

      // Produce new state by modifying draft
      this.setState(draft => {
        draft.count += num
      })

      // ..or merge into new state
      this.setState({
        count: this.state.count + 1
      })

      // Optionally call other actions
      this.actions.action()
    },

    // Action can be async
    async action(props) {}
  }  
}

const store = createStore(storeProps)

store.on('action', (key, props) =>{
  console.log('Action called', key, props)
  console.log('State changed', store.state)
})

store.actions.increment(5)

console.log(store.state) // { count: 5 }

Immutability

const oldState = store.state

store.actions.increment(5)

const newState = store.state // oldState !== newState

store.state.count++ // Error, must use setState or action

Core

If immutability is not needed, there's a much smaller core that can be imported.

import { createStore } from 'medux/core'

It has the same interface, but instead of using immer, it will mutate the store's state with Object.assign. This is simpler and faster, but does not have the benefits of immutability.

Context

For the createStore function, one can pass a property context with an object.


const storeContext = {}

createStore({
  context: storeContext
})

This is available to actions as this.context.

Events

The store instance is an event emitter with methods on, off, and emit.

They can be accessed from actions as this.on, this.off, this.emit.


const handler = data => {}

// Subscribe
store.on('eventName', handler)

// Unsubscribe
store.off('eventName', handler)

// Emit event

const data = {}

store.emit('eventName', data)

The on function returns an unsubscriber, which can be called with no arguments.

Child stores

const store = createStore({
  
  createState: () => ({
    ...parentState,
    child: childState
  }),

  actions: {
    ...parentActions,
    child: childActions
  }
})

store.actions.child.increment(5)

console.log(store.state.child) // { count: 5 }

Compose stores

The method composeStore creates a store from an array of store props.

This is a way to merge sets of states and actions.

import { composeStore } from 'medux' // or medux/core

const feature = {
  state: {},
  actions: {}
}

const anotherFeature = {
  state: {},
  actions: {}
}

const store = composeStore([
  feature,
  anotherFeature
], context)

Redux DevTools

import { connectReduxDevTools } from 'medux/redux-devtools'

const store = useStore(storeProps)

connectReduxDevTools(store)

React

The method useStore connects a component to a store, to render on state changes.

import { useStore } from 'medux/react'

const Component = () => {

  const store = useStore(storeProps)
  const { state, actions } = store

  return <button onClick={() => actions.increment()}>
    Increment: { state.count }
  </button>
}

It also accepts an array of store props, in which case their states and actions will be merged using composeStore.

The store can also be created outside the component, and passed to useStore.

import { createStore } from 'medux'
import { useStore } from 'medux/react'

const store = createStore(storeProps)

const Component = () => {

  useStore({ store })
  const { state, actions } = store

  return <button onClick={() => actions.increment()}>
    Increment: { state.count }
  </button>
}

React with Redux DevTools

import { useEffect } from 'react'
import { useStore } from 'medux/react'
import { connectReduxDevTools } from 'medux/redux-devtools'

const Component = () => {

  const store = useStore(storeProps)

  useEffect(() => {
    connectReduxDevTools(store)
  }, [])

  return ..
}

With options for Redux DevTools

connectReduxDevTools(store, options)

With store instance name

connectReduxDevTools('App', store, options)

Develop this library

Install dependencies

yarn

Develop: Watch files; Recompile, type check and test on changes

yarn dev

Build

yarn build

Publish to NPM

npm run release