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

react-state-reducer

v1.4.0

Published

A simple (non-feature complete) ~clone~ reimplementation of [Redux](https://redux.js.org) built using React 16.3's `createContext`.

Downloads

32

Readme

React-State-Reducer

A simple (non-feature complete) ~clone~ reimplementation of Redux built using React 16.3's createContext.

Example:

import React, { Fragment } from 'react'
import createStore from 'react-state-reducer'

const INITIAL_STATE = {
  count: 0,
}

const counterReducer = action => (
  state = INITIAL_STATE,
) => {
  switch (action.type) {
    case 'INC':
      return { count: state.count + 1 }
    case 'DEC':
      return { count: state.count - 1 }
    default:
      return state
  }
}

const { Provider, Consumer } = createStore(counterReducer)

export default () => (
  <Provider>
    <Consumer>
      {({ count, dispatch }) => (
        <Fragment>
          <button onClick={() => dispatch({ type: 'DEC' })}>
            -
          </button>
          {count}
          <button onClick={() => dispatch({ type: 'INC' })}>
            +
          </button>
        </Fragment>
      )}
    </Consumer>
  </Provider>
)

API:

There are two core parts of react-state-reducer's API that should be kept in mind.

Reducers:

The first is the reducer. A reducer is a higher order function (meaning it returns a function), that first accepts an action and returns a function that accepts the current state (and optionally any props provided to the <Provider>). This returned function should then handle returning the updated state.

That was a lot of different words describing what this is, lets look at some code to walk through this.

  1. Lets start with the higher order function:
const myReducer = someAction => {
  return (state) => {
    ...
  }
}

This function accepts a single argument (someAction) and returns a function. Which in turn accepts a single argument called state. This is often written as the following:

const myReducer = action => state => { ... };
  1. Handling updates within the returned function:
const myReducer = action => state => {
  if (action === 'SOME_UPDATE') {
    return {
      ...state,
      someKey: '🆒',
    }
  }
}

Some notes with this implementation above:

  • It doesn't follow the generic Redux reducer concept of using a switch you can handle writing this function however you would like (using switch, or using an if/else)

  • Right now we are implicitly returning undefined if action does not equal 'SOME_UPDATE', while this is valid, you should make sure to at least handle returning the initial state if the action is the following shape:

{type: '@@INIT', payload: null}

What this looks like in practice:

const todoReducer = action => (state = { todos: [] }) => {
  switch (action.type) {
    case 'ADD_TODO': {
      return {
        todos: [
          ...state.todos,
          {
            id: state.todos.length,
            completed: false,
            text: action.payload,
          },
        ],
      }
    }
    case 'CHECK_TODO': {
      return {
        todos: todos.map(todo => {
          if (todo.id === action.payload) {
            return {
              ...todo,
              completed: !todo.completed,
            }
          } else {
            return todo
          }
        }),
      }
    }
    default:
      return state
  }
}

createStore:

createStore is the main export of react-state-reducer, it is a function that accepts a reducer as an argument. It calls the reducer with the initialization action:

yourReducer({ type: '@@INIT', payload: null })(null)

and then uses the result of calling the reducer as the initial state for the store. createStore then returns an object with the following:

{
  Provider: Node,
  Consumer: Node
}

Provider

The Provider component exposes two props, the first is children which can be a single component, or many components.

The second prop is onUpdate which is a function that will be called after each state update happens, it is called with the updated state.

<Provider
  onUpdate={newState => {
    /* Maybe sync state to localStorage, or something else */
  }}
>
  <App />
</Provider>

Consumer

The Consumer component has one core prop, children, children is a function that gets called with an object with the following keys:

  • dispatch
  • top level keys from state

For example if your state shape looks like this:

{
  todos: [],
  text: ''
}

the consumer children function would look like the following:

<Consumer>
  {({
    dispatch,
    todos,
    text
  }) => (
    ...
  )}
</Consumer>

Consumer also optionally supports a selector prop, which can either take in an array of functions or a single function to select your slice of state you care about:

<Consumer selector={s => s.todos}>
  {({ dispatch }, todos) => {
    /* */
  }}
</Consumer>

Redux

This library is highly influenced by all the great work put into Redux and React-Redux. For some more information on the differences between this library and Redux see redux.