Skip to content
/ storem Public

A reactive store for global state management in JS

License

Notifications You must be signed in to change notification settings

Lesnock/storem

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Storem

A reactive store of data for global state management in JS.

Installation

npm install storem
// OR
yarn add storem

Usage

Getting Started

In store.js file:

import { Store } from 'storem';

const store = new Store();

export default store;

In otherfile.js file:

import store from './store'

store.set({ name: 'John' })

// When "name" changes in the store, this callback will be executed
store.listen('name', (value, oldValue) => {
  if (value !== oldValue) {
    console.log(`name changed to ${value}`)
  }
})

store.set({ name: 'Mary' }) // Will emit the event binded before - name changed to 'Mary'

store.get('name') // Mary

store.delete('name')

store.get('name') // undefined

Creating the store

To start using Storem we should create a file to instantiate the store and export it:

// store.js
import { Store } from 'storem';

const store = new Store({ persist: true });

export default { store };

Obs: Storem does not have support for multiple stores yet.

Configurations

Storem can receive a configuration object as the constructor argument. Below are the available options:

  • persist Determines if the data should be persisted throughout the pages (uses localStorage, so it is only available in the browser)

  • debug Turn on debug mode. If enabled, all store changes will be logged in the console.

  • reactOnDelete If true, will execute the callback events when data is deleted from the store.

Example:

import { Store } from 'storem'

const store = new Store({
  persist: true,
  debug: true,
  reactOnDelete: false
})

API Methods

set

To add data to the store or update an existing data, we use the set method:

import { Store } from 'storem'

const store = new Store()

store.set({ name: 'John' }) // Will create the data "name" with value "John"

store.set({ name: 'Mary' }) // Will update the data "name" to "Mary"

get

Fetch a specific field from the store:

const name = store.get('name')

all

Fetch all data from the store.

const storeData = store.all()

// Using destructuring assignment
const { name, age, address } = store.all()

only

Retrieves specifics fields from the store. This method will return an object with the required data:

const data = store.only(['name', 'age', 'address'])
// { name: 'John', age: 23, address: 'Lombard Street' }

// Using destructuring assignment
const { name, age, address } = store.only(['name', 'age', 'address'])

has

Verify if a data exists in the store:

store.add({ name: 'John' })

store.has('name') // true

delete

You can aswell delete a data from the store

store.set({ name: 'John' })
store.delete('name')

console.log(store.get('name')) // undefined

The reactive part

Storem is reactive to data change. This means that Storem can detect all data changes in your application. It's possible to attach an event callback to be executed whenever a specific data is updated in the store. This is a powerfull tool, since it can be used to globally sinchronize all components of your application.

listen

Listen to changes in a specific data in the store, and once it changes, the callback function is executed. The callback function will receive the current value and the old value as arguments:

store.set({ activeLesson: 1 })

// Listen to changes in the activeLesson data, and executes the callback
store.listen('activeLesson', (value, oldValue) => {
  console.log('Active Lesson has changed to: ' + value)
}

The listen method is where the magic happens. You can synchronize all components within your application listening to changes in the store.

Example:

// Whenever cart items changes, total value is recalculated
store.listen('cartItems', (cardItems) => {
  recalculateTotal(cardItems)
})

Mutations

Mutations are functions that can be registered in the store to alter his data. It is possible to create a mutation using the setMutation method, passing name and function as arguments. The passed function will receive the complete store state as argument. Let's create a mutation that increment a counter, for example:

// Create a counter inside the store
store.set({ counter: 1 })

// Create a mutation to increment the counter
store.setMutation('INCREMENT', state => {
  state.counter++
})

To run a mutation, we use the runMutation method passing the mutation name as argument:

store.runMutation('INCREMENT') // Increment counter
store.runMutation('INCREMENT') // Increment counter again

console.log(store.get('counter')) // 3

You can either pass arguments to mutations:

// Create quantity data inside the store with value 0
store.set({ quantity: 0 })

// Create mutation receiving a "quantity" argument
store.setMutation('ADD_QUANTITY', (state, quantity) => {
  state.quantity += quantity
})

store.runMutation('ADD_QUANTITY', 10) // Will add 10 to state.quantity

console.log(store.get('quantity')) // 10

Obs: Storem does not react to data change inside mutations. In others words, listeners will not be executed when data changes occurs inside a mutation.

Persisting Data

If you want the data to persist throughout the pages, and refreshes, just set the persist config to true in the store configs. With this config, Storem will save the data in the localStorage, and will automatically load it from there when the page refreshes or the user change the route. Storem state will be the same, regardless of page change. This will NOT work in the Node enviroment, just in the browsers.

// Set persist to true when creating the store
const store = new Store({
  persist: true,
})

It's important to mention that, if you persist the data, when you refresh or change the page in your application, Storem will load the data automatically from localStorage, but if you set a data manually to the store, it will overwrite the data that was loaded from localStorage. So, if you want to avoid that behaviour, you can check if a data already exists before set the data:

if (!store.has('name')) {
  store.set({ name: 'John Doe' })
}

// OR
!store.has('name') && store.set({ name: 'John Doe' })

Using Storem with React

Storem works well with React, either. In order to use a store in React, the most important thing is to sinchronyze the component rendering with the data in the store. Storem makes this easy.

Look at how to sinchronyze a component with the store:

import React, { useState, useEffect } from 'react'
import store from './store'

export default function Name() {
  const [name, setName] = useState(store.get('name') || 'John Doe')

  // Synchronize the component state with store data whenever it changes
  useEffect(() => {
    store.listen('name', value => setName(value))
  }, [])

  // Function to change the name
  const changeName = () => {
    store.set({ name: 'Mary' })
  }

  return (
    <div>
      <span>{name}</span>
      <button onClick={changeName}>Change name</button>
    </div>
  )
}

About

A reactive store for global state management in JS

Resources

License

Stars

Watchers

Forks

Packages

No packages published