2.5.2 • Published 5 months ago

aio-store v2.5.2

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

publish version dependencies size MIT License

AIO-STORE

State management for any javascript application. It's tiny, fast, stable, contains no boilerplate, has no side effects, doesn't need a context provider and compatible with SSR. It comes with zero dependencies and lets you dispatch actions from anywhere. Typescript user or Javascript user, it doesn't matter. It is all for you.

Installation

  npm install aio-store

Usage

Let's import createStore

// All users, No hook
import { createStore } from "aio-store";

// React user with hook
import { createStore } from "aio-store/react";

Create a store

Just create your store, No actions is needed

export const useExpStore = createStore({
  exp: 10,
});

Use the store

  • Anywhere in your app
const store = myStore.get()
  • Inside a React component
import { useExpStore } from "./store";

const MyComponent = () => {

  // Realtime update for React users
  const { exp } = useExpStore();

  // ❗ this is just a snapshot, No realtime changes
  const { exp } = useExpStore.get();

  // ❗ this is just a snapshot, No realtime changes
  const exp = useExpStore.get("exp");

  // Realtime update available for React users
  const { exp } = useExpStore("*");

  // Deep data with realtime update
  const deepValue = useExpStore("data.depp.moreDeep");

  return <span>{exp}</span>;
};
  • With selector

Get your store and return whatever you want in any format

import { useExpStore } from "./store";

const MyComponent = () => {
  
  const { exp } = useExpStore(store => ({exp: store.exp}));
  
  const [exp,other] = useExpStore(store => [store.exp,store.other]);
  
  const exp = useExpStore(store => store.exp);

  // Deep data with realtime update
  const deepValue = useExpStore(store => store.data.depp.moreDeep);

  // ❗ Just a snapshot, No realtime changes
  const exp = useExpStore.get(store => store.exp);

  return <span>{exp}</span>;
};
  • With listener

You can listen to your store changes anywhere in your app and update something stateless. Very useful when you want to eliminate unnecessary rendering.

const myStore = createStore(...);

// Listen to all changes
myStore.listen('*', (data) => {
  // while listening, you can get a snapshot to do some control
  // React user or vanilla users
  const snap = myStore.get()
  
  // vanilla users
  const snap = myStore()
  
  const someValue = myStore.get("someValue")
  // do what ever you want with your data,
})

// Listen to specific changes
myStore.listen('data.content.value', (data) => {
  // while listening, you can get a snapshot
  const snap = myStore.get()
  const someValue = myStore.get("someValue")
  // do what ever you want with your data,
})

The listen method returns an unsubscribe function

const unsubscribe = myStore.listen('data', (data) => {})

unsubscribe()

Limit render

By default aio-store use strict equality to prevent unnecessary render. For more control, you can use any data equality function as long as it returns a boolean.

// String selector
const data = myStore("data",(oldValue, newValue) => sameOrNot)

// Function selector
const data = myStore(store => store.data, (oldValue, newValue) => sameOrNot)

// Listener selector
const data = myStore("data",callback, (oldValue, newValue) => sameOrNot)

Mutation

Your store is immutable, you will always get a fresh store. When you mutate your store, Please be aware that, storeRef or whatever the name you call it, point to a reference of your store. So do not override the reference.

Mutate Object

const myStore = createStore({
  myValue: 10,
})
myStore.set(storeRef => {
  // ❌ Bad, Don't do this.
  storeRef = {
    myValue: 11
  }
})

Instead, do like following lines

const myStore = createStore({
  myValue: 10,
})

myStore.set(storeRef => {
  storeRef.MyValue = 11
  // ✅ Good,
  storeRef.MyValue = {
    // ...whatever you want
  }
  // ✅ Good, you can add new Props
  storeRef.newProp = {
    // ...whatever you want
  }
  // ✅ Good,
  storeRef.props.data = {
    someData: someValue
    // ...whatever you want
  }
  // ✅ Good, if props.data already exists
  storeRef.props.data.someData += someValue
})

Mutate Array

const myStore = createStore({
  arr: [{name: "default"}],
})

myStore.set(storeRef => {
  // Mutation inside the array
  storeRef.arr[0].name = "New name";
  storeRef.arr.push("new item")
// Mutation with new array or clean the array
  storeRef.arr.length = 0
  // Or 
  storeRef.arr = []
})

Mutate Map / Set

const myStore = createStore({
  map: new Map(),
  set: new Set(),
  setContainsMap: new Set().add(new Map()),
  mapContainsSet: new Map().set("mySet",new Set()),
})
// Mutation inside the array
myStore.set(storeRef => {
  // Mutation inside a map
  storeRef.map.set("new Key", "new value")
  // Mutation inside a set
  storeRef.set.add("new value")
  // Mutation inside setContainsMap
  storeRef.setContainsMap.forEach(s => {
    // S is a Map
    s.set("new Key", "new value")
  })
  // Mutation inside mapContainsSet
  storeRef.mapContainsSet.get("mySet").add("new Value")
  // Cleaning
  storeRef.mapContainsSet.clear()
  storeRef.setContainsMap.clear()
})

Transferring the ref

When you do not want to repeat yourself, It is useful to save a reference of the updated part and use it multiple times. But always take care of not destroying that reference

const myStore = createStore({
  data: {
    deep: {
      moreDeep: {}
    }
  }
})

myStore.set(storeRef => {
  const moreDeep = storeRef.data.deep.moreDeep;
  
  // Use moreDeep ✅
  moreDeep.newProp1 = "new value 1"
  moreDeep.newProp2 = "new value 2"

  let deep = storeRef.data.deep;

  // Use moreDeep ✅
  deep.moreDeep = {
    newProp1: "new value 1",
    newProp2: "new value 2"
  }

  let moreDeep = storeRef.data.deep.moreDeep;
  
  // ❌ you are destroying the reference.
  // ❌ moreDeep is not pointing anymore the real moreDeep.
  // ❌ It has a new reference
  moreDeep = {
    newProp1: "new value 1",
    newProp2: "new value 2"
  }
  // But This is fine ✅
  // Because the storeRef is in charge
  storeRef.data.deep.moreDeep = {
    newProp1: "new value 1",
    newProp2: "new value 2"
  }
})

Available tools and options

  • createStore Let you create a store
  • set A property attached to your store that lets you dispatch actions from any file.
  • get A Function attached to your store that lets you get a snapshot of your store at any time.
  • listen A Function attached to your store that lets you listen to changes in all or specific part of your store.
  • * A key that can be passed to your store in order to get everything or to listen to all changes in your store.

License

MIT

2.5.2

5 months ago

2.5.1

5 months ago

2.5.0

5 months ago

2.4.44

5 months ago

2.4.43

5 months ago

2.4.42

6 months ago

2.4.41

6 months ago

2.4.4

6 months ago

2.4.3

7 months ago

2.4.2

7 months ago

2.4.1

7 months ago

2.4.0

8 months ago

2.3.3

8 months ago

2.3.2

8 months ago

2.3.1

8 months ago

2.3.0

8 months ago

2.2.2

8 months ago

2.2.1

8 months ago

2.2.0

8 months ago