UNPKG

frontend-hamroun

Version:

A lightweight frontend JavaScript framework with React-like syntax

99 lines (98 loc) 2.85 kB
/** * Global state management solution similar to Redux */ import { useState, useEffect } from './hooks.js'; import { createContext, useContext } from './context.js'; import { jsx } from './jsx-runtime.js'; export function createStore(reducer, initialState, middlewares = []) { let state = initialState; let listeners = []; // Apply middlewares let dispatch = (action) => { state = reducer(state, action); listeners.forEach(listener => listener()); return action; }; // Chain middlewares if (middlewares.length > 0) { const middlewareAPI = { getState: () => state, dispatch: (action) => dispatch(action), subscribe: (listener) => subscribe(listener) }; const chain = middlewares.map(middleware => middleware(middlewareAPI)); dispatch = chain.reduce((a, b) => (next) => a(b(next)))(dispatch); } // Subscribe to store changes function subscribe(listener) { listeners.push(listener); return function unsubscribe() { listeners = listeners.filter(l => l !== listener); }; } // Initialize store with default state dispatch({ type: '@@INIT' }); return { getState: () => state, dispatch, subscribe }; } export const StoreContext = createContext({ store: { getState: () => ({}), dispatch: () => { }, subscribe: () => () => { } }, state: {} }); export function StoreProvider({ store, children }) { const [state, setState] = useState(store.getState()); useEffect(() => { const unsubscribe = store.subscribe(() => { setState(store.getState()); }); return unsubscribe; }, [store]); return jsx(StoreContext.Provider, { value: { store, state }, children }); } export function useSelector(selector) { const context = useContext(StoreContext); return selector(context.state); } export function useDispatch() { const context = useContext(StoreContext); return context.store.dispatch; } export function useStore() { const context = useContext(StoreContext); return context.store; } // Common middlewares export const logger = (store) => (next) => (action) => { console.group(action.type); console.log('Previous state:', store.getState()); console.log('Action:', action); const result = next(action); console.log('Next state:', store.getState()); console.groupEnd(); return result; }; export const thunk = (store) => (next) => (action) => { if (typeof action === 'function') { return action(store.dispatch, store.getState); } return next(action); }; export default { createStore, StoreProvider, useSelector, useDispatch, useStore, logger, thunk };