Skip to content

Instantly share code, notes, and snippets.

@gustavoguichard
Created April 16, 2021 19:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gustavoguichard/23cf4c71c8d3f9e3aac57174da781ec6 to your computer and use it in GitHub Desktop.
Save gustavoguichard/23cf4c71c8d3f9e3aac57174da781ec6 to your computer and use it in GitHub Desktop.
Global state
import { useState, useEffect } from 'react'
function setState(newState, updateContext) {
this.state = { ...this.state, ...newState }
this.listeners &&
this.listeners.forEach(([context, listener]) => {
updateContext === context && listener(this.state)
})
}
function useCustom(context) {
const [, newListener] = useState()
useEffect(() => {
this.listeners && this.listeners.push([context, newListener])
return () => {
this.listeners = this.listeners
? this.listeners.filter(([, listener]) => listener !== newListener)
: []
}
}, [newListener, context])
return [this.state, this.actions]
}
function associateActions(store, actions) {
const associatedActions = {}
actions.forEach((value, key) => {
if (typeof value === 'function') {
associatedActions[key] = value.bind(null, store)
}
if (typeof value === 'object') {
associatedActions[key] = associateActions(store, value)
}
})
return associatedActions
}
export default (actions, initialState = {}) => {
if (!actions) {
throw new Error('You need to set up some actions')
}
const store = {
state: initialState,
listeners: [],
setState: () => null,
}
store.setState = setState.bind(store)
store.actions = associateActions(store, actions)
return useCustom.bind(store)
}
@gustavoguichard
Copy link
Author

gustavoguichard commented Apr 16, 2021

Usage:

// store.js
import useStore from './useStore'

const initialState = {
  menuOpen: false,
  page: 'home'
}

const actions = {
  toggleMenu: async (store) => {
     store.setState({ menuOpen: !store.state.menuOpen })
  },
  changePage: (store, page) => {
    store.setState({ page })
  },
}

const store = useStore(actions, initialState)

export default store

Usage in a component

import useGlobal from './store.js'

const MyComponent = (props) => {
  const [{ menuOpen, page }, { changePage, toggleMenu }] = useGlobal()
  return <div onClick={menuOpen}>{page}</div>
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment