Skip to content

Instantly share code, notes, and snippets.

@helabenkhalfallah
Last active April 28, 2024 07:55
Show Gist options
  • Save helabenkhalfallah/7a51b0eeee56049a5d1b228849aaf494 to your computer and use it in GitHub Desktop.
Save helabenkhalfallah/7a51b0eeee56049a5d1b228849aaf494 to your computer and use it in GitHub Desktop.
Subscribing a functional component to reactive store changes
import React, { useState, useEffect } from "react";
// Function to create a reactive store
function createStore(initialState) {
// Store the initial state in a private variable
let state = initialState;
// Array to hold subscribers (callbacks)
const subscribers = [];
// Create a proxy for the state object
const stateProxy = new Proxy(state, {
// Trap for setting a property value
set: function(target, property, value, receiver) {
// Update the value of the property
target[property] = value;
// Trigger callbacks (subscribers) with the updated state
subscribers.forEach((callback) => callback(stateProxy));
// Indicate success
return true;
},
});
// Function to get the current state
function getState() {
return stateProxy;
}
// Function to subscribe to state changes
function subscribe(callback) {
subscribers.push(callback);
// Return a function to unsubscribe
return function unsubscribe() {
const index = subscribers.indexOf(callback);
if (index !== -1) {
subscribers.splice(index, 1);
}
};
}
// Return the getter, setter, and subscribe functions
return {
getState,
subscribe,
};
}
// Usage example
const store = createStore({ count: 0 });
// Function component to render UI based on state
function Counter() {
// State to hold the current state of the store
const [state, setState] = useState(store.getState());
// Effect to subscribe to state changes when the component mounts
useEffect(() => {
// Subscribe to state changes
const unsubscribe = store.subscribe((newState) => {
// Update the local state with the new state from the store
setState({ ...newState });
});
// Return the unsubscribe function to clean up subscriptions
return () => {
unsubscribe();
};
}, []);
// Effect to increment the count every 5 seconds
useEffect(() => {
// Set up a timer to increment the count every 5 seconds
const interval = setInterval(() => {
// Update the count in the store's state
store.getState().count += 1;
}, 5000);
// Clear the interval timer when the component unmounts
return () => {
clearInterval(interval);
};
}, []);
// Render the count from the local state
return <div>Count: {state.count}</div>;
}
export default Counter;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment