Git Product home page Git Product logo

aprilmintacpineda / fluxible-js Goto Github PK

View Code? Open in Web Editor NEW
15.0 2.0 1.0 9.42 MB

Smaller, faster, better event-driven state management architecture that supports asynchronicity and state persistence out of the box with no extra code.

License: MIT License

JavaScript 90.28% Shell 0.06% TypeScript 9.66%
state-management state-pattern asynchronous-state-management synchronous-state-management global-states global-state-store

fluxible-js's Introduction

npm npm npm

Fluxible-JS v6

Smaller, faster, better event-driven state management architecture that supports asynchronicity and state persistence out of the box with no extra code.

Change logs

From 5.0.10, the changelogs on the project will be kept in CHANGELOG, which follows keepachangelog.

Demo

demo-typings_J13zCqab.mp4

Run me

  1. git clone [email protected]:aprilmintacpineda/fluxible-js.git
  2. yarn
  3. yarn test

Install

yarn add fluxible-js

Usage

import { createStore } from 'fluxible-js';

const initialStore = {
  user: null,
  someOtherState: 'value',
  anotherState: {
    value: 'value'
  }
};

const store = createStore({
    initialStore,
    persist: {
      stringify: true,
      syncStorage: {
        setItem: (key, value) =>
          window.localStorage.setItem(key, value as string),
        getItem: key => window.localStorage.getItem(key)
      },
      restore: savedStore => ({
        user: savedStore.user
      })
    }
  });

Creating a store

import { createStore } from 'fluxible-js';

const initialStore = {
  user: null,
  someOtherState: 'value',
  anotherState: {
    value: 'value'
  }
};

function initCallback () {
  console.log('initialization complete');
}

const myStore = createStore({ initialStore }, initCallback);

createStore function returns an instance of a store that has variety of methods in it. You can access the store's current value by via myStore.store. The 2nd parameter which is the initCallback is optional function that gets called after the store has been initialized, this is especially useful when using async storage.

Persisting states

Persisting states allows you to save your application's state to a storage on the local device and then reuse those states the next time your application starts.

You need to tell fluxible-js which storage to use, a storage API must have a getItem and setItem methods in them. An example of this would be window.localStorage or React-Async-Storage

You also need to tell fluxible-js which states to persist, you can do this via the restore callback function.

You need to tell fluxible-js if the states has to be stringified (using JSON.stringify) before being saved to the storage by specifying stringify parameter.

Using asynchronous storage

setItem and getItem should be async or should return a promise, pretty much like with React-Native-Async-Storage. See example use-case with react-fluxible.

import { createStore } from 'fluxible-js';

const initialStore = {
  token: null,
  isLoggedIn: false,
  initComplete: false
};

const store = createStore(
  {
    initialStore,
    persist: {
      stringify: true,
      asyncStorage: {
        setItem: (key, value) => someAsyncStorage.setItem(key, value as string), // value will be a string because `stringify` is set to `true`
        getItem: key => someAsyncStorage.getItem(key) // has to be a string because `stringify` is set to true
      }
      restore: (savedStore) => {
        return {
          token: savedStore.token
        };
      }
    }
  },
  () => {
    store.updateStore({ initComplete: true });
  }
);

Using synchronous storage

getItem and setItem should be sync, pretty much like with window.localStorage. See example use-case with react-fluxible.

import { createStore } from 'fluxible-js';

const initialStore = {
  token: null,
  isLoggedIn: false
};

const store = createStore({
  initialStore,
  persist: {
    stringify: true,
    syncStorage: {
      setItem: (key, value) =>
        window.localStorage.setItem(key, value as string), // value will be a string because `stringify` is set to `true`
      getItem: key => window.localStorage.getItem(key) // has to be a string because `stringify` is set to true
    },
    restore: (savedStore) => {
      return {
        token: savedStore.token
      };
    }
  }
});

If you don't care that much about typings, you can also just do:

syncStorage: window.localStorage as SyncStorage<typeof initialStore>,

or

syncStorage: ReactNativeAsyncStorage as AsyncStorage<typeof initialStore>,

Updating the store

You can update the store by doing:

import { createStore } from 'fluxible-js';

const initialStore = {
  token: null,
  isLoggedIn: false
};

const store = createStore({
  initialStore,
  persist: {
    stringify: true,
    syncStorage: {
      setItem: (key, value) =>
        window.localStorage.setItem(key, value as string),
      getItem: key => window.localStorage.getItem(key)
    },
    restore: (savedStore) => {
      return {
        token: savedStore.token
      };
    }
  }
});

// somewhere in your code
store.updateStore({
  token: userToken,
  isLoggedIn: true
});

Adding observers

Observers are callback functions that listen to certain changes in your store. Observers will be called AFTER the store has been updated and they will receive the updated store. You can add an observer by doing:

import { createStore } from ".";

const store = createStore({
  initialStore: {
    token: null
  }
});

store.addObserver(
  (store) => {
    console.log(store.token);
    // do something
  },
  // states that you want to watch changes for
  ['token']
);

Observers will only be called when the state they are watching changes, in this case, the observer is only watching token, so this observer will only be called when you do store.updateStore({ token }). This prevents unnecessary calls to all observers when other states changes.

Events

You can add, emit, and remove events in your store. You can take advantage of events to do various things in your applications such as updating the store.

Adding events

import { createStore } from ".";

const store = createStore({
  initialStore: {
    token: null
  }
});

/**
 * Event callbacks receive the:
 * payload = passed on emitEvent
 * store = the latest value of thes store
 * event = the event that was emited, this is useful when using `addEvents`
 */
const unsubscribeCallback = store.addEvent('test-event', (payload, store, event) => {
  console.log(payload, store, event);
  // do something
});

// when you want to remove the event listener from the event
unsubscribeCallback();

There is also addEvents in case you want an event listener to listen to multiple events.

const unsubscribeCallback = store.addEvents(
  ['event1', 'event2', 'event3'],
  (payload, store, event) => {
    console.log(payload, store, event);
    // do something
  }
);

// when you want to remove the event listener from the event
unsubscribeCallback();

Emitting an event

store.emitEvent(
  'event1',
  // optional: any value you want to pass to all the event listeners
  { value: 1 }
);

Emitting multiple events

store.emitEvents(
  ['anEvent', 'anotherEvent'],
  // optional: any value you want to pass to all the event listeners
  { value: 1 }
);

Removing an event

store.removeEvent('event1');

Removing multiple events

store.removeEvents(['anEvent', 'anotherEvent']);

Migrating from v5 to v6

The only changes that occured in v6 are the following:

  • Used TypeScript for better coding experience.
  • Changed architecture to be more self-contained.
  • No more -1 returns.

Your code should still work with minimal changes. Here's how you can migrate real quick.

Create a file called globalStore.ts, and add the following code:

import { createStore } from 'fluxible-js';

const initialStore = {
  // ... your store values here
};

export default createStore({
  initialStore,
  // ... other options
});

Now, change all occurences of import { updateStore } from 'fluxible-js'; and other similar imports to import { updateStore } from 'globalStore';.

fluxible-js's People

Contributors

aprilmintacpineda avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

lanceliamll

fluxible-js's Issues

BUG: calling update listeners is inefficient

Migrated from: aprilmintacpineda/inferno-fluxible#1 (comment)

https://github.com/aprilmintacpineda/inferno-fluxible/blob/master/src/index.js#L38

Consider the following:

let a = [1, 2, , 3, 4];

for (b = 0; b < a.length; b++) {
  if (a.length > 100) {
    console.log('demo succeeded');
    break;
  }

  console.log(a[b]);
  a.push('_' + b);
}

In the code above, variable a's elements increases in length, therefore, the for loop more than expected.

The code below fixes it:

let a = [1, 2, , 3, 4];
const limit = a.length;
console.log('limit:', limit);

for (b = 0; b < limit; b++) {
  if (a.length > 100) {
    console.log('demo succeeded');
    break;
  }

  console.log(b, ':', a[b]);
  a.push('_' + b);
}
console.log('done');

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.