MarkGeeRomano / Smol-Store

A simple, redux-inspired global store for electron apps ⚛️
3 stars 0 forks source link
electron redux state-management

Smol-Store

A smol redux-inspired store for your electron app.

Installation

npm install smol-store

Philosophy

Sure, there are other libraries out there that achieve the same, but this lib is very smol, it's dumb simple (~75 lines of code), and the API consists of only 4 functions.

This was implemented from scratch in an @araBlocks electron application. It's been a real asset, so it's been pulled out and packed into an npm module.

Usage

//reducers.js
module.exports = {
 aNumber: (state, load) => {
  switch (load.type) {
    case 'ADD_1':
      state += 1
      break
    case 'ADD_2':
      state += 2
      break
    default:
      state += load.value
    }
    return state
  }
}
//state.js
module.exports = { aNumber: 0 } //property names must match reducer names
//main.js (root of electron app)
const smolStore = require('smol-store')
const state = require('./state')
const reducers = require('./reducers')

smolStore.initialize(state, reducers))//initialize needs to be called before API can be used

//set regular listeners for main process - call `dispatch` when heard
ipcMain.on('increment_1', () => smolStore.dispatch({ type: 'ADD_1' }))
ipcMain.on('increment_2', () => smolStore.dispatch({ type: 'ADD_2' }))
ipcMain.on('increment_custom', (event, value) => smolStore.dispatch({ type: 'CUSTOM', load: { value } }))
//index.js (script for index.html)
const { ipcRenderer } = require('electron')
const { subscribe, state } = require('smol-store')

document.getElementById('button1').onclick = () => ipcRenderer.send('increment_1')
document.getElementById('button2').onclick = () => ipcRenderer.send('increment_2')
document.getElementById('button3').onclick = () => ipcRenderer.send('increment_custom', Math.random())

const display = document.getElementById('display')

display.innerText = state.aNumber//`state` is the object created in state.js, made global through `initialize`

//the callback passed into `subscribe` will be called when the `state` has been changed.
subscribe(() => display.innerText = state.aNumber)

API

someReducerName(state, load)

A function that corresponds to a property on the state that holds instructions for modifying that piece of the state, based on the type value the load holds. Must be called in main process

initialize(state, reducers, [opts])

Sets the initial app state and creates the dispatch function you'll use to update your state.

state

A getter function that returns the state. Stored in the main process' global variable.

dispatch(load)

Dispatches an object to all reducers to modify the state accordinly. Will emit a 'REFRESH' message to all subscribed renderer processes after updating state. Must be called in main process.

subscribe(callback)

Emits a 'SUBSCRIBE' message from the given renderer process to the main process to ensure it emits a 'REFRESH' message to it when state has changed. Creates a listener for the message, and upon the deletion of the given render process, emits an 'UNSUBSCRIBE' message to the main process. Must be called in renderer process.