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

easy-react-state

v1.0.9

Published

Fun to use state management library for your awesome React app

Downloads

18

Readme

easy-react-state

Managing your app state should be easy and fun. easy-react-state is a minimal library for creating state management for your React project.

NPM

Install

npm install --save easy-react-state
or
yarn add easy-react-state

Features

  • easy to adopt with. Just think of React.useState where it has multiple setters which update the state object.
  • reduce boilerplate codes. No need to create actions. Just call and pass the right data.
  • intuitive selector system.
  • minimal API. Don't need to use some helper functions to support async updates.
  • typescript supports.

Usage

1 - Configuring your store

const configAppStore = {
  todos: {
    initialState: [],
    setters: state => ({
      addTodo(todo) {
        state.push(todo)
        return state
      },
    }),
  },
}

2 - Creating state manager based on your store

const [useAppSelector, appSetters] = createStateManager(configAppStore)

3 - Consume to your React Component

We don't need a Provider to consume the store. Just create a manager, then you can use it directly.

const App = () => {
  const todos = useAppSelector(state => state.todos)
  console.log('todos', todos)
  return (
    <div>
      <h3>Todos Control</h3>
      <button
        onClick={() => {
          const todo = {
            id: `todo-${Date.now()}`,
            label: `Todo ${Date.now()}`,
          }
          appSetters.todos.addTodo(todo)
        }}
      >
        Add todo
      </button>
    </div>
  )
}

Use setters inside async

Our setters are object which holds all the state setters. Upon creating, we can call setters just like normal functions. Indeed, we can call it everywhere. No need wrapper function like thunk to make it possible. Just call it immediately!

const [useAppSelector, appSetters] = createStateManager(configAppStore)

async function fetchUsers() {
  appSetters.users.loading()
  try {
    const res = await apiUsers()
    appSetters.users.setUsers(res)
  } catch (err) {
    appSetters.users.setError(err)
  }
}

Invoking setters outside React

React will batch the updates for subsequent calls of setters. But if you call these setters outside the React event system, like Promise or setTimeout, then every call will cause a re-render to Component. To avoid this, you can wrap your setters inside the ReactDOM.unstable_batchedUpdates.

import { unstable_batchedUpdates as batch } from 'react-dom'

// No batching
const Test1 = () => {
  React.useEffect(() => {
    // This will cause 2 renders
    setTimeout(() => {
      obj1.setter1()
      obj2.setter2()
    })
  }, [])
  return <div>Test 1</div>
}

// With batching
const Test2 = () => {
  React.useEffect(() => {
    setTimeout(() => {
      // Single render
      batch(() => {
        obj1.setter1()
        obj2.setter2()
      })
    })
  }, [])
  return <div>Test 2</div>
}

API

Type Interfaces

interface CreateState<S = any> {
  initialState: S
  setters: (state: S) => any
}

interface ConfigStore {
  [x: string]: CreateState
}

interface Options {
  label?: string
  logging?: boolean
}

interface Store<S, U> {
  getState: () => S
  subscribe: (Listener: Listener) => () => void
  setters: U
}

interface Selector<S> {
  <T>(
    selector: (state: S) => T,
    equalityFn?: (prevSelectedState: T, nextSelectedState: T) => boolean,
  ): T
}

interface Setter {
  (...args: any[]): any
}

createStateManager

createStateManager(configStore: ConfigStore, options?: Options): [useSelector, setters, store]

This function creates a resources which we can use to manage the state based on the configStore. It also return a store object.

store

store: Store<State, Setters>

An object which we can use to get the current state, subscribe and update state through setters. Its interface is just like redux-store.

useSelector

useSelector: Selector

A function which we can use to extract data from the store state using a selector function. useSelector semantics are pretty the same with useSelector of react-redux. The difference is useSelector of react-redux uses strict === reference equality. Unlike useSelector of easy-react-state, it uses Object.is for comparing selectedState. Check react-redux for more info. useSelector supports the selector created by reselect.

setters

setter(...args: any[]): S

An object which holds functions which we can use to update the state. easy-react-state uses the amazing immerjs. When updating a state, you can use mutator syntax like state.name = 'zion' for ease. Every setter must return the mutated state or new value. Internally, the state gets mutated inside the setter is a draftState created by immer. Then immer will create a new object based on the value, either draftState or new value, returned by setter leaving the originalState untouchable. Note the setters which are returned by createStateManger are now wrappedSetters. If the passed setters are returning state. Then this wrappedSetters are now returning void.

Cons

  • doesnt have DevTools for now. But it has logging option.
  • it doesnt support nested state. All state are resided at the top level object.

License

MIT © ombori