IniZio / iniz

:shipit: A reactive state library for ReactJS
https://iniz.netlify.app/
MIT License
90 stars 1 forks source link
preactjs reactjs state-management

Iniz

Iniz is a reactive state library for ReactJS. Try it out on our website!

npm i @iniz/core

Build Status Test Coverage Build Size Version Downloads

Guide

Getting started

Create an atom / store

import { atom, store } from "@iniz/core";

const timer$ = atom(new Date());

const nested$ = store({
  obj: {
    array: [{ count: 3 }],
    message: "Hello World",
  },
  async reset() {
    this.array = [];
    this.message = "Good bye";
  },
});

Mutate the atom value

Call the atom to read/write it.

// Initial value
timer$(); // Returns latest value e.g. `2019-08-31T00:00:00.000Z`

// Mutate the atom / state
setInterval(() => {
  nested$.obj.array[0].count++;
  timer$(new Date());
}, 1000);

// Later on...
timer$(); // Returns latest value e.g. `2022-08-31T00:00:00.000Z`
nested$.obj.array[0].count;

nested$.reset();

Subscribe to atom

Use effect() to subscribe to value change.

const dispose = effect(() => {
  console.log("Updated timer: ", timer$());
});

// Execute `dispose` to stop effect
dispose();

Use computed() to get calculated value from multiple atoms.

const timerAndCounter$ = computed(
  () => `Computed: '${nestedCounter$().obj.array[0]}' '${timer$()}'`
);

timerAndCounter$(); // Returns "Computed: 2022-08-31T00:00:00.000Z 4"

React ⚛

npm i @iniz/react

@iniz/react already re-exports @iniz/core, so don't need to install @iniz/core yourself

Simply use atom() values in components, they will re-render correctly thanks to useSyncExternalStore

import { useAtom, useComputed } from "@iniz/react";

// The component won't re-render when `nestedCounter$().obj.array[0].count` is updated
function MessageInput() {
  // Equivalient to `atom()`
  const counter = useAtom(10);

  // Equivalent to `computed()`
  const computedCounter = useComputed(
    () => `Computed: ${nestedCounter$$().obj.message}`
  );

  // Equivalent to `effect()`
  // NOTE: You can also use `useEffect` with atoms actually
  useSideEffect(() => {
    console.log("[Latest message] ", computedCounter());
  });

  return (
    <div>
      <button onClick={() => counter(counter() + 1)}>{counter()}++</button>
      <input
        value={nestedCounter$().obj.message}
        onChange={(evt) => (nestedCounter$().obj.message = evt.target())}
      />
    </div>
  );
}

Credits