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-xs

v1.0.33

Published

Minimalism state manager

Downloads

25

Readme

react-xs

Logo

Minimalism state manager

Features

| | react-xs | redux | | ------------------------- | :------: | :---: | | Provider element | | ✓ | | Action Dispatcher | | ✓ | | Action Creator | | ✓ | | Reducer | | ✓ | | Middleware | | ✓ | | connect() HOC | | ✓ | | State Mappings / Bindings | | ✓ |

react-xs has nothing special but it is powerful, easy to use, reduce code complexity and great performance

Table of contents

  1. Counter App
  2. Todo App
  3. Creating simple state
  4. Handling state change
  5. Getting state value
  6. Sub States
  7. Binding states to component
  8. Mutating multiple states and performance issue
  9. Mutating state using helpers
  10. Handling multiple states change
  11. Computed state
  12. Getting values of multiple states
  13. Update values of multiple states
  14. Dispatching function one time when component did mount
  15. Best practice
  16. API
  17. Credits

Counter App

Simplest and shortest counter app

import React from "react";
import { render } from "react-dom";
import $ from "react-xs";
const count = $(1);
const Counter = $(() => (
  <>
    <h1>{count.value}</h1>
    <button onClick={() => count.value++}>Increase</button>
  </>
));
render(<Counter />, document.getElementById("root"));

Compare to redux version

import React from "react";
import { render } from "react-dom";
import { createStore } from "redux";
import { Provider, connect } from "react-redux";

const reducer = (state = 0, action) => {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    default:
      return state;
  }
};

const store = createStore(reducer);

const App = connect(state => ({ count: state }))(({ dispatch, count }) => (
  <>
    <h1>{count}</h1>
    <button onClick={() => dispatch({ type: "INCREMENT" })}>Increase</button>
  </>
));

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

Redux like version

import React from "react";
import { render } from "react-dom";
import $ from "react-xs";
const connect = $;
const Count = $(1);
const Increase = () => Count.value++;
const Counter = connect(
  {
    // map state to props
    states: { count: Count },
    // dispatch to props
    actions: {
      increase: Increase
    }
  },
  ({ count, increase }) => (
    <>
      <h1>{count}</h1>
      <button onClick={increase}>Increase</button>
    </>
  )
);
render(<Counter />, document.getElementById("root"));

Todo App (Performance test)

Please refer this link , an example runs with 7000 todo items (over 28.000 elements). User can update todo text on the fly, without lagging. Redux or other state managers(Mobx, unstated) get lag with 1000-5000 todo items

Creating simple state

import $ from "react-xs";

const numberValue = $(100);
const booleanValue = $(true);

// mutate states
numberValue.value = 1000;
booleanValue.value = false;

// keep in mind, state can be anything, no validation or restriction for state data type
numberValue.value = new Date();

Handling state change

import $ from "react-xs";

const state = $(1);
state.subscribe(nextValue => console.log(nextValue));
state.value = 100;

Getting state value

import $ from "react-xs";

const person = $({ name: "Hung", address: { street: "abc", city: "def" } });
person.value.name; // Hung
person.get("name"); // Hung
person.get`name`; // Hung

person.get("address.street"); // abc
person.value.address.street; // abc
person.get`address.street`; // abc

Sub States

const person = $({ name: "Hung", address: { street: "abc", city: "def" } });
person.prop`address.street`.value; // abc
person.prop(`address.street`).value; // abc

Binding states to component

You can use overload $(component) to create component wrapper which binded with states. You dont need any Provider element, no mapStateToProps needed

import React from "react";
import $ from "react-xs";
const state = $(1);
const WrappedComponent = $(props => {
  return <div>{state.value}</div>;
});

Mutating multiple states and performance issue

Sometimes you need to mutate many states at same time, that might lead to performance issue because when state changed, it notifies to all components which is using state

import React from "react";
import $ from "react-xs";

const state1 = $(1);
const state2 = $(2);

const Comp1 = $(() => <div>{state1.value}</div>);
const Comp2 = $(() => (
  <div>
    {state1.value}
    {state2.value}
  </div>
));

function DoSomething() {
  state1.value = 100; // at this time, both Comp1 and Comp2 re-render
  state2.value = 100; // Only Comp2 re-renders
}

We can use $.mutate(action) to reduce component re-render times

function DoSomething() {
  $.mutate(() => {
    state1.value = 100;
    state2.value = 100;
  });
  // Comp1 and Comp2 re-render one time only
}

Mutating state using helpers

react-xs provides many helpers for mutating object, array, date, number, boolean, string data types

import $ from "react-xs";

const number = $(0);
number.add(1); // 1
number.add(-2); // -1
number.mul(2); // -4
number.div(2); // -2

const obj = $({});
obj.set("name", "Hung"); // { name: 'Hung'  }
obj.toggle("male"); // { name: 'Hung', male: true  }
obj.prop`parent.address.street`.value = "abc"; // { name: 'Hung', male: true, parent: { address: { street: 'abc' } }  }
obj.unset("parent", "male"); // { name: 'Hung'  }
// set default value for prop if it is not present
obj.def("male", false); // { name: 'Hung', male: false  }
// nothing affected because male prop is present
obj.def("male", true); // { name: 'Hung', male: false  }

const array = $([]);
array.push(1, 2, 3); // [1, 2, 3]
array.splice(1, 1); // [1, 3]
array.map(x => x * 2); // [2, 6]
array.pop(); // [2]
array.shift(); // []
array.unshift(1, 2); // [1, 2]
array.filter(x => x % 2 === 0); // [2]
array.push(5, 6, 2); // [2, 5, 6, 2]
array.exclude(2); // [5, 6]
array.remove(1); // [5]
array.fill(100); // [100]
array.push(99); // [100, 99]
array.first() === 100; // true
array.last() === 99; // true
array.sort(); // [99, 100]

const date = $(new Date("2019-01-01"));

date.add(1, "Y"); // add 1 year, 2020-01-01
date.add(1, "year"); // add 1 year, 2021-01-01
// duration can be year/Y, month/M, day/D,
// hour/h, minute/m, second/s, milli
// you also add multiple durations
date.add([1, "M"], [2, "D"]); // add 1 month and 2 days, 2021-02-03

If you want to extend more helpers, just call $.extend()

import $ from "react-xs";
import immhelper from "immhelper";

$.extend({
  update(specs) {
    return this.mutate(current => immhelper(current, specs));
  }
});
const state = $({
  name: "N/A"
});

state.update({
  name: ["set", "Hung"]
});

// { name: 'Hung' }

Handling multiple states change

import $ from "react-xs";

const state1 = $(0);
const state2 = $(0);

$.subscribe([state1, state2], () => {
  console.log("test1", state1.value, state2.value);
});

// using debounce option
$.subscribe(
  [state1, state2],
  (state1Value, state2Value) => {
    console.log("test2", state1Value, state2Value);
  },
  {
    debounce: 100
  }
);

state1.value = 1;
state2.value = 2;

// output
// test1 1 0
// test1 1 2
// test2 1 2

Computed state

import $ from "react-xs";

const state1 = $(1);
const state2 = $(2);
const state3 = $().compute([state1, state2], () => state1.value + state2.value); // state3 = 3
state1.value = 100; // state3 = 102
state2.value = 101; // state3 = 201

Getting values of multiple states

import $ from "react-xs";

const state1 = $(1);
const state2 = $(2);

$.get({
  state1,
  state2
}); // { state1: 1, state2: 2 }

Update values of multiple states

import $ from "react-xs";

const state1 = $(1);
const state2 = $(2);
const state3 = $(3);
$.set(
  {
    state1,
    state2
  },
  {
    state1: 5,
    state2: 6,
    state3: 7
  }
);
// state1 = 5
// state2 = 6
// state3 = 3

Dispatching function one time when component did mount

import React from "react";
import { render } from "react-dom";
import $ from "react-xs";

// assign default async status to state value
// initial { loading:false, done:false, data:undefined, error:undefined }
// loading { loading:true, done:false, data:undefined, error:undefined }
// resolved { loading:false, done:true, data:any, error:undefined }
// rejected { loading:false, done:true, data:undefined, error:any }
const userProfile = $().async();
const LoadUserProfile = () => {
  // do nothing if we already fetched data
  if (userProfile.get`done`) {
    return;
  }
  // update state once promise resolved/rejected
  userProfile.async(
    fetch("https://demo9029075.mockable.io/react-xs-user-profile").then(res =>
      res.json()
    )
  );
};

const UserProfileComponent = $(() => {
  // dispatch LoadUserProfile once when component did mount
  $.one(LoadUserProfile);

  // render userProfile according to its states
  return userProfile.async({
    loading: "Loading...",
    success: data => JSON.stringify(data)
  });
});

render(<UserProfileComponent />, document.getElementById("root"));

Best practice

Sometimes we try to split our app to many modules, it is hard for other state management libraries. Here is sample project structure if you are using react-xs

modules/counter/states.js

import $ from "react-xs";
export const CountState = $(0);

modules/counter/actions.js

import { CountState } from "./state.js";

export function Increase() {
  CountState.value++;
}

export function Decrease() {
  CountState.value--;
}

export async function Load() {
  const payload = await fetch(
    "https://demo9029075.mockable.io/react-xs-counter"
  ).then(res => res.json());

  CountState.value = payload.count;
}

// auto increase count each 3s
setInterval(Increase, 3000);

modules/counter/components/container.js

import { CountState } from "../state.js";
import { Increase, Decrease, Load } from "../actions.js";
import $ from "react-xs";

export default $.hoc(props => {
  return {
    ...props,
    count: CountState.value,
    increase: Increase,
    decrease: Decrease,
    load: Load
  };
});

modules/counter/components/index.js

import React from "react";
import container from "./container";

export default container(({ count, increase, decrease, load }) => {
  return (
    <>
      <h1>{count}</h1>
      <button onClick={increase}>Increase</button>
      <button onClick={decrease}>Decrease</button>
      <button onClick={load}>Load</button>
    </>
  );
});

Working with class component

You can use react-xs with any component types, even class component. That helps you bring react-xs power to old components and refactor them all to functional components later

import React, { Component } from "react";
import { render } from "react-dom";
import $ from "react-xs";

const Count = $(0);
const Increase = () => Count.value++;
class Counter extends Component {
  _ = $.bind(this);

  render = () => (
    <>
      <h1>{Count.value}</h1>
      <button onClick={Increase}>Increase</button>
    </>
  );
}
render(<Counter />, document.getElementById("root"));

API

Credits