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 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-innate

v0.0.1

Published

...

Readme

react-lean

The react-lean is a minimalist state management react library as an alternative to Redux and Mobx focused in lean coding and declarative component supporting asynchronous state, rollback handlers, loading flag, publish-subscriber, etc (only compatible with babeljs transpiler).

React state management challenge

As react state management problem is covers by three issues: verbosity, complexity and strictivity.

| PROBLEMS | FEATURES | | ----------- | --------------------------------------------------------- | | VERBOSITY | Boilerplate code and over-work coding | | COMPLEXITY | Huge detail concerns and long learning curve | | STRICTIVITY | Its high complexity demands large complex apps use cases. |

To deal with that problem and maintains the unidirectional data flow approach of React, it demands not just a new tool or library, but a new pattern.

Features

  • lean state management
  • async fetching support
  • rollback/undo feature
  • publisher-subscriber
  • loading screen flag

Patterns

The flux data-flow pattern is an architectural pattern alternative to MVC and MVVM (data binding). Its main difference it its unidirectional approach with claimed better performance in comparison with MVC or MVVM. This react-lean lib follows a data flow that I named just "reflow", as bellow. The tool step is a set of library functions that changes data and data updates the view.

| NAME | DIAGRAM | | :--: | :-----------------------: | | MVC | mvc | | MVVM | mvvm | | FLUX | flux | | CCC | aflux |

In CCC pattern, a store-component encapsulates a global object as its store, meanwhile its children state-components uses triggers a stage-commander that acts like a special "controller", but not between model and view, but between a state-component and a store-container.

A performance concern may come up with that root rendering propagating throughout multiple components, instead a single render component, but the virtual DOM react algorithm guarantees that only its differences with real DOM will be propagated. Conceptually, it is a overall rendering, but in practice, that algorithm ensure an individual case-by-case rendering component.

The stage-commander is a set of functionalities that covers three kind of component state changings: sync, async and resync. A sync state changing is the most basic state management and in React Hooks is represented by useState, meanwhile, async state changing demands useEffect hook. At last, what I call "resync state changing" is a pub-sub pattern behavior that decouples event trigger to event listener, and allowing subscribing/unsubscribing events.

In Flux/Redux there are a kind of two patterns: CQRS (reducer as handler, actions as commands, selector as queries) and pub-sub pattern (type name as 'topic', mappers as subscribing topics). It is not surprising its huge extra-work with that double pattern implementation. Although, with CCC/React-Lean, we have a kind of unidirectional MVC (as Flux), with its better performance results and, at same time, and optional pub-sub resource. Then, meanwhile flux-redux demands some scale to starting worthy due its high implementation costs and high complex data-flow, react-lean is adaptable with any application scale.

Purpose

The main purpose for a lean state management is promote a leaner and cleaner code implementing with pure functional components (or just declarative components),

  • Class Component: WORSE...
class Counter extends React.Component {    
 constructor(props) { super(props); this.state = { count: 0 }; }

 render() {
   return (
     <div>
       <p>count: {this.state.count} times</p>
       <button onClick={() => this.setState({ count: this.state.count + 1 })}>
         Click
       </button>
     </div>
   );
 }
}
  • Functional Component: BETTER... (with react hooks)
const Counter = props => {
 const [count, setCount] = React.useState(0);

 return <div>
     <p>count: {count}</p>
     <button onClick={() => setCount(count + 1)}>Click</button>
   </div>
}
  • Declarative Component: BEST... (with react-lean tools)
const Counter = props => 
   <div>
     <p>count: {state.count}</p>
     <button onClick={() => setState(x => x.count++)}>Click</button>
   </div>

Usage

The next examples is created with React Native.

Sync state management

a) storing: store{object}, state, setState(function)

Storing states is very simple, it starts with store props in Provider and is changed by a setState function, but not that this setState receives a function parameter as in follow example.

  • App.js
import React from 'react'
import { Provider } from 'react-lean'
import Hello from './hello'

const helloWorldStore = { name:string }

const App = props => 
   <Provider store={helloWorldStore}> 
      <Hello />
   </Provier>
  • hello.js
import React from 'react'
import { View, Text, TextInput } from 'react-native'
import { state, setState } from 'react-lean'

const Hello = props => 
   <View>
      <Text>Hello {state.name || "World"}!</Text>
      <TextInput value={state.name} onChangeText={texting} />
   </View>

const texting = text => setState(s => s.name = text);

b) undoing: letState(function), onBack{object}

The letState allowed to rollback behavior by saving the current state a triggering the back button handler in onBack props on Provider, as exemplified in next example.

  • App.js
import React from 'react'
import { Provider } from 'react-lean'
import Todo from './todo'

const handler = {handler:BackHandler, trigger:'hardwareBackPress'};
const todos = { list:[], text:"", done:false }

export default App = props =>
   <Provider store={todos} onBack={handler} >
      <Todo title="TODO list" />
   </Provider>
  • todo.js
import React from 'react'
import { View, Text } from 'react-native'
import { Input, Icon, Checkbox } from 'react-native-elements'
import { state, setState } from 'react-lean'

const Todo = props => 
   <View>
      <Text>{props.title}</Text>
      <Input value={state.text} onChangeText={texting} /> 
      <Button title="Add" onPress={adding} />
      <TodoList />
   </View>

const TodoList = props => state.list.map((x,i) => <TodoItem key={i} {...x} />)
                   
const TodoItem = props =>
   <View style={{flexDirection:'row'}}>
      <Checkbox checked={props.done} onPress={checking}  />
      <Text>{props.text}</Text>
      <Icon name="delete" onPress={removing(props.key)} />
   </View>

const adding = _ => letState(s =>s.list.push(s.item))
const texting => x => setState(s => s.text = x);
const checking => _ => setState(s => s.done = !s.done)
const removing => k => setState(s => s.list = s.list.filter((x,i) => i != k))

c) parsing: getState(string)

With getState is possible get states with string representation, for example, you could access the object state.user.name as getState("user.name") as next.

const Hello = props => 
   <View>
      <Text>Hello {state.name || "World"}!</Text>
      <Text>Hello {getState("name") || "World"}!</Text>
   </View>

Fetching: inload, onload, unload

a) async reading: inload -> unload

The inload reads a async state receiving a function as argument that, since returns a void, you can avoid imperative coding just adding a getState followed by "||" in function head as bellow.

const Todo = props => getState(listing) ||
   <View>
      <Text>{props.title}</Text>
      <Input value={state.text} onChangeText={texting} /> 
      <Button title="Add" onPress={adding} />
      <TodoList />
   </View>

The listing function examplo concludes with unload function with handle number argument. That argument manages the side effects to avoid endless rendering loop.

const listing = handle => axios
   .get("http://any.api.exemple/todo")
   .then(x => setState(s => s.list = x.data))
   .catch(err => console.error(err))
   .finally(() => unload(handle));

b) async writing: onload -> unload

The onload function wraps an event function mading three thinsgs: set loading flag to false, render the component view and prevent render looping with handle number argument.

const Todo = props => getState(listing) ||
   <View>
      <Text>{props.title}</Text>
      <Input value={state.text} onChangeText={texting} /> 
      <Button title="Add" onPress={adding} />
      <TodoList />
   </View>

const adding = e => axios
   .create(someAxiosConfig)
   .post("/todo", state.item)
   .catch(console.error)
   .finally(() => unload(e))

c) async writing-reading: onload -> inload -> unload

In a very common use case, if you want to start a loading state when requesting to insert an item with API and continue to reloading with listing function, just do that, passing on the handle argument to listing function.

const adding = e => axios
   .create(someAxiosConfig)
   .post("/todo", state.item)
   .then(() => listing(e)); // insted unload(e), pass on to listing(e);

Publish-Subscribe

For complete decouple between event triggers on components and event listeners in functions, the react-lean offer an simple API for publish-subscribe pattern.

a) listening topics

A listener is a function factory that create an listener object,

const howAreYou = listener("how are you?", true,  x => console.log("Great!"));
const andYou = listener("and you?", true, x => console.log("I'm fine too!"));

b) subscribing listeners

Listeners must be subscribed inside of a component, in that case, some imperative coding is needed, letting way the pure functional component for a more conventional way.

const Hello = props => 
{   
   subscriber(howAreYou, true); // true = subscribe, false = unsubscribe
   subscriber(andYou, true); // true = subscribe, false = unsubscribe
    
   return <View>
      <Text>Hello {state.name || "World"}!</Text>
   </View>
}

c) publishing topics with payloads (optional)

In next example, these buttons triggers some topics (without payloads in that example) that will catch by subscribed listeners in effortful way.

const ExampleComponent = props =>
   <View>
      <Button title="how are you?" onPress={_ => publisher("how are you"?)} />
      <Button title="and you?" onPress={_ => publisher("and you?")} />    
   </View>

Reference

// wrapper component conteiner for state management
export class Provider {
   store:any;
   onLoadTimeout:number = 7000;
   onBack:BackButtonEventHandler;
}

// exposed readonly global state
export var state:any;

// loading flag state for handling loading screen
export var loading:boolean;

// all registered by inload function for publisher-subscriber behavior
export var subscriptions:Subscription[];

// The setState is the main change write-only function of react-lean
// ex.: setState(state => state.name = "john");
export function setState(f:changer):void;

// letState is a setState variation to rollbackin states (undo feature)
export function letState(f:changer):void;

// getState a state by string representation
// ex.: getString("user.name") as state.user.name
export function getState(f:changer):void;

// it encapsulates an event function and sets loading flag to 'true'
export function onload(f:charger):void;

// ending loading cycle and, optionally, emit a topic for subscribers
export function unload(handle:number):void;

// loading async fetching states as a managed useEffect 
export function inload(f:changer):void;

// subscribe a listener object to respond a topic event
export function subscriber(topic:string, adding:boolean):void

// publish a trigger topic with optional payload value
export function publisher(topic:string, value:any = null):void

// criate a listener object to be handled by subscriber
export function listener(topic:string, f:action, render:boolean):Listener

// changer is a function type as arguments for effectfull global setState
export interface changer { (model:any):void; }
export interface charger { (model:any):(any) => void; }

/// function type that represent a function
export interface action { ():void; }

// listener class to be used with subscriber
class Listener { topic:string; f:action; render:boolean; }

// that type represents a mapped back button to react-lean
class BackButtonEventHandler { handler:IHandler; trigger:string; }

// that type represents a subscription realized by inload function
class Subscription { topic:string;  render:boolean; action:()=>void; }

// interface for event listener for undo feature
export interface IHandler { addEventListener(handler:any, trigger:string) }