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

@chipsgg/react-wiring

v3.3.3

Published

High performance and fine grained change subscriptions using React Hooks.

Downloads

143

Readme

React Wiring

High performance and fine grained change subscriptions using React Hooks.

Install

yarn add @chipsgg/react-wiring

Quick Start

import React from 'react'
import Wiring from 'react-wiring'

//default state you want your component props to see
const initialState = {
  initialized:false
}

//design your state reducers
const reducers = {
  initialize(state,initialized){
    return {
      ...state,
      initialized
    }
  }
}

const [
  useWiring, //use this inside react component to get state and dispatch
  store      //use this outside react to play with state
] = Wiring(React,reducers,initialState)


//this is the main app using the connect function.
const App = props=>{
  //you want to listen to the 'initialized' property on state
  //it is optional to listen for changes, if omitted you will just get latest state
  const [state,dispatch] = useWiring('initialized')
  const {initialized} = state

  return <div>
    Initialized? {initialized.toString()}
    <Button onClick={e=>dispatch('initialize',true)} />
  </div>
}


//initilize react app
const anchor = document.getElementById("app");            
ReactDOM.render(                                           
  //You do not need a provider
  <App/>,
  anchor                                                  
)

API

Construction

  import Wiring from 'react-wiring'
  const [useWiring,store] = Wiring(React,reducers,initialState={})

Input(React,reducers,initialState={})

  • React - pass in your React object v16.8 or higher (requires hooks)

  • reducers - A plain object with reducer functions as values

  • reducer(state,...dispatchArguments)=>state - A named callback function with current state passed in and any user provided arguments.

    • state - the current state in the store ( do not modify in reducer)
    • ...dispatchArguments - parameters passed in from dispatch call, can be anything
    • => state - the new state after reducer runs
      const reducers = {
        setBalance(state,amount){
          return {
            ...state,
            balance:{
              ...state.balance,
              amount
            }
          }
        },
        addBalance(state,add){
          return {
            ...state,
            balance:{
              ...state.balance,
              amount:state.balance.amount + add
            }
          }
        }
      }
  • initialState - An object with anything in it as your starting state

Output => [useWiring,store]

  • useWiring - the use wiring hook for inside a React component
  • store - the data store which allows you to get, set, dispatch and listen to state changes outside of React

useWiring

Use wiring can only be called within a React component

  // in a component
  const [state,dispatch,curryDispatch,get] = useWiring(subscriptions,...resubscribe)

  //if you only need certain return values, this is valid
  const [,,curry,get] = useWiring(subscriptions,...resubscribe)

Input useWiring(subscriptions,...resubscribe)

  • subscriptions - This is how you subscribe to state changes, and can be defined in many ways:
    • undefined - render will happen once and no more
    • string - a single string to listen to one property on state, in lodash path notation. An empty string will subscribe you to any state changes.
    • Array<string> - an array of strings in lodash path notion, allows you to listen to multiple changes. An empty array will subscribe you to any state changes.
    • Array<Array<string>> - an array of arrays of strings, like [['path','a'],['path','b']]
    • function isEqual(prev,next)=>boolean - a function which takes the previous state and next state and returns true if no change happens or false if a change happens this is exactly the same as React.memo
  • resubscribe - Optional arguments for data that lives outside of the store which may require a new subscription on change. For the most part you only need this if you have variables in your path subscriptions that are dynamic.

Output => [state,dispatch,curryDispatch,get]

Outputs an array of parameters that should be destructured.

  • state - Your store state
  • function dispatch(action,...arguments) - a function which takes and action and arguments
    • action - a string or array of strings which represent the path to the reducer function
    • arguments - all arguments get passed into reducer
    • example: login(username,password).then(x=>dispatch('showSuccess','Login Complete')).catch(err=>dispatch('showError',err))
  • function curryDispatch(action)=>(...arguments) - a function which returns the call for arguments
    • example: login(username,password).then(x=>curryDispatch('showSuccess')('Login Complete')).catch(curryDispatch('showError'))
  • function get(path,defaults) - a function which will allow lodash notation to get properties inside the state and avoid runtime errors.
    • path - a string or array in lodash path notation. If not specified will return entire state.
    • defaults - an optional parameter to return if the data is undefined at that path

Store

The store allows you to listen to state change and mutate state outside of React.
  const [_,store] = Wiring(React,reducer)
  const {dispatch,curry,set,get,on,off} = store

Properties

  • store.dispatch(action,...arguments) - Call a reducer and specify arguments
    • action - a string or array of strings which represent the path to the reducer function
    • arguments - all arguments get passed into reducer
  • store.curry(action)(...arguments) - Call a reducer in a curried way.
    • action - a string or array of strings which represent the path to the reducer function
    • arguments - all arguments get passed into reducer
  • store.get(path,defaults) - return current state or partial state based on path in lodash path notation.
    • path - a string or array in lodash path notation. If not specified will return entire state.
    • defaults - an optional parameter to return if the data is undefined at that path
  • store.set(state) - set state and trigger all listeners. Anything passed in here replaces the state.
  • store.on(callback,subscriptions)=>off - subscribe to state changes
    • callback(state) - callback expects a single input which is the store state
    • subscriptions - optional field to subscribe to key changes on state, defined above in useWiring
    • => off() - return unsubscribe function
  • store.off(callback) - unsubscribe by passing callback function subscription in

Guide

Combine Reducers

Redux has a combineReducers function. You can get close to this functionality by composing your reducer objects. This does not provide any performance improvents and is just organizational.

//user-reducer.js
export default {
  updateUserName(state,name){
    return {
      ...state,
      'user':{...state.user,name}
    }
  }
}
//wallet-reducer.js
export default {
  setBalance(state,balance){
    return {
      ...state,
      'wallet':{...state.wallet,balance}
    }
  }
}
//combine-reducers.js
import users from './user-reducer'
import wallets from './wallet-reducer'
import Wiring from 'react-wiring'
import React from 'react'

export default const reducers = { 
  users,
  wallets,
}
//wiring.js
import reducers from './combine-reducers'

export default const [useWiring,store] = Wiring(React,reducers)
import {useWiring} from './wiring'

//using it in a component
export function Balance(props){
  //listen to wallet and user properties on state for changes using
  //lodash path notation.
  //the state returned is your unmapped global store state
  const [{user,wallet},dispatch] = useWiring(['wallet.balance','user.name'])

  //see how we call the reducer as lodash path notation
  //you can nest your reducer objects indefinately this way
  return <div>
    {user.name} has ${wallet.balance}
    <button onClick={e=>dispatch('wallets.setBalance',0)}>
      Clear Balance
    </button>
  </div>
}

Add Reducers at Runtime

Because the reducer is a javascript object we can just attach new keys at any point.


const reducers = { 
  users,
  wallets,
}

const [useWiring,store] = Wiring(React,reducers)

//This could be added at any point, lets say if user was authenticated
reducers.admin = {
  makeAdmin(state,isAdmin=true){
    return {
      ...state,
      user:{...state.user,isAdmin}
    }
  }
}

//dispatch can now call
store.dispatch('admin.makeAdmin',true/false)