UNPKG

@diginet/use-reactive

Version:

A reactive state management hook for React.

61 lines 2.77 kB
import React, { createContext, useContext, useRef } from "react"; import { useReactive } from "./useReactive"; // Assuming your existing function /** * Creates a globally shared reactive state using React Context and useReactive. * * @param initialState The initial state object * @returns {ReactiveStoreProvider, useReactiveStore} Context provider and hook */ export function createReactiveStore(initialState, options) { // Create the context and provider const ReactiveStoreContext = createContext(null); const ReactiveStoreProvider = ({ children }) => { // Create the reactive state const [state, subscribe, history] = useReactive(initialState, { ...options, noUseState: true }); // Return the provider return (React.createElement(ReactiveStoreContext.Provider, { value: [state, subscribe, history] }, children)); }; /** * Hook to access the reactive state and subscribe to changes. * * @returns {ReactiveStoreContext<T>} The reactive state and subscribe function */ const useReactiveStore = () => { const context = useContext(ReactiveStoreContext); if (!context) { throw new Error("useReactiveStore must be used within a ReactiveStoreProvider"); } const [, setTrigger] = React.useState(0); // Create a proxy to track the subscriptions const proxyProxy = useReactive(context[0], { noUseState: true }); // Track the subscriptions const subscriptionsRef = useRef(null); if (!subscriptionsRef.current) { subscriptionsRef.current = new WeakMap(); } const removerRef = useRef(null); if (!removerRef.current) { // Subscribe to the proxy to track the subscriptions removerRef.current = proxyProxy[1](() => proxyProxy[0], function (state, key, _value, _previous, read) { // Get the map of subscriptions for the state let map = subscriptionsRef.current.get(state); if (!map) { // Create a new map if it doesn't exist map = new Map(); subscriptionsRef.current.set(state, map); } // Check if the key is not already subscribed if (read && !map.has(key)) { // Subscribe to the key map.set(key, true); context[1](() => state[key], () => { setTrigger((prev) => prev + 1); }); } }, 'deep', true); } return [proxyProxy[0], context[1], context[2]]; }; return [ReactiveStoreProvider, useReactiveStore]; } //# sourceMappingURL=useReactiveStore.js.map