Last active
April 28, 2024 07:55
-
-
Save helabenkhalfallah/7a51b0eeee56049a5d1b228849aaf494 to your computer and use it in GitHub Desktop.
Subscribing a functional component to reactive store changes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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