New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

storeon

Package Overview
Dependencies
Maintainers
1
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

storeon

Tiny (196 bytes) event-based Redux-like state manager for React and Preact

  • 0.1.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
16K
decreased by-2.33%
Maintainers
1
Weekly downloads
 
Created
Source

Storeon

A tiny event-based Redux-like state manager for React and Preact.

  • Small. 196 bytes (minified and gzipped). No dependencies. It uses [Size Limit] to control size.
  • Immutable. The same Redux reducers, but already with syntax sugar on top.
  • Modular. API created to move business logic away from React components.
import createStore from 'storeon'

// Initial state, reducers and business logic are packed in independent modules
let increment = store => {
  // Initial state
  store.on('@init', () => ({ count: 0 }))
  // Reducers can return only changed part of the state
  store.on('inc', ({ count }) => ({ count: count + 1 }))
}

export const store = createStore([increment])
import { connect } from 'storeon/react' // or storeon/preact

const Counter = ({ count, dispatch }) => {
  return <div>
    {count}
    <button onClick={() => dispatch('inc')}
  </div>
}
export default connect('count', React.memo(Counter))
import { StoreContext } from 'storeon/react'

render(
  <StoreContext.Provider value={store}>
    <Counter></Counter>
  </StoreContext.Provider>,
  document.body
)
Sponsored by Evil Martians

Usage

Store

The store should be created with createStore() function. It accepts list of the modules.

Each module is just a function, which will accept store and bind their event listeners.

// store/index.js
import createStore from 'storeon'

import projects from './projects'
import users from './users'

export const store = createStore([projects, users])
// store/projects.js

export default store => {
  store.on('@init', () => ({ projects: [] }))

  store.on('projects/add', ({ projects }, project) => {
    return projects.concat([project])
  })
}

The store has 3 methods:

  • store.get() will return current state. The state is always an object.
  • store.on(event, callback) will add event listener.
  • store.dispatch(event, data) will emit event with optional data.

Events

There are three built-in events:

  • @init will be fired in createStore. The best moment to set an initial state.
  • @dispatch will be fired on every store.dispatch() call. Can be useful for debugging.
  • @changed will be fired every when event listeners changed the state.

To add an event listener, call store.on() with event name and callback.

store.on('@dispatch', ([event, data]) => {
  console.log(`Storeon: ${ event } with `, data)
})

store.on() will return cleanup function. This function will remove event listener.

const unbind = store.on('@changed', …)
unbind()

You can dispatch any other events. Just do not start event names with @.

If the event listener returns an object, this object will update the state. You do not need to return the whole state, return an object with changed keys.

// count: 0 will be added to state on initialization
store.on('@init', () => ({ users:  { } }))

Event listener accepts the current state as a first argument and optional event object as a second.

So event listeners can be a reducer as well. As in Redux’s reducers, you should change immutable.

store.on('users/save', ({ users }, user) => {
  return {
    users: { ...users, [user.id]: user }
  }
})

store.dispatch('users/save', { id: 1, name: 'Ivan' })

You can dispatch other events in event listeners. It can be useful for async operations.

store.on('users/add', async (state, user) => {
  try {
    await api.addUser(user)
    store.dispatch('users/save', user)
  } catch (e) {
    store.dispatch('errors/server-error')
  }
})

Components

You can bind the store to React and Preact component with connect() decorator.

import { connect } from 'storeon/react' // Use 'storeon/preact' for Preact

const Users = ({ users, dispatch }) => {
  const onAdd = useCallback(user => {
    dispatch('users/add', user)
  })
  return <div>
    {users.map(user => <User key={user.id} user={user} />)}
    <NewUser onAdd={onAdd} />
  </div>
}

export default connect('users', React.memo(Users))

connect() will re-render on any state changes. It is important for performance to wrap all your component into React.memo or define shouldComponentUpdate.

connect() accept the list of state keys to pass into props. Or you can pass a function to convert state to props.

const mapToProps = ({ projects }) => ({
  activeProjects: projects.filter(i => i.active)
})

export default connect(mapToProps, React.memo(Projects, deepEqual))

Keywords

FAQs

Package last updated on 16 Mar 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc