<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Lere's blog]]></title><description><![CDATA[Lere's blog]]></description><link>https://writing.lere.cc</link><generator>RSS for Node</generator><lastBuildDate>Sun, 17 May 2026 17:07:28 GMT</lastBuildDate><atom:link href="https://writing.lere.cc/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Implementing a tiny global store in React]]></title><description><![CDATA[Have you ever wondered how state management libraries like Zustand or Jotai work under the hood? These libraries are incredibly useful for sharing global state across your application without the complexity of prop drilling or external context provid...]]></description><link>https://writing.lere.cc/implementing-a-tiny-global-store-in-react</link><guid isPermaLink="true">https://writing.lere.cc/implementing-a-tiny-global-store-in-react</guid><category><![CDATA[React]]></category><category><![CDATA[State Management ]]></category><category><![CDATA[Global State Management]]></category><dc:creator><![CDATA[Olaitan Ibrahim]]></dc:creator><pubDate>Fri, 01 Aug 2025 22:00:00 GMT</pubDate><content:encoded><![CDATA[<p>Have you ever wondered how state management libraries like Zustand or Jotai work under the hood? These libraries are incredibly useful for sharing global state across your application without the complexity of prop drilling or external context providers.</p>
<p>In this article you will learn how to implement a small replica of a global store using the observer pattern. This pattern allows different subscribers to listen to changes in a central piece of state and be notified whenever that state is updated.You can learn more about the observer pattern <a target="_blank" href="https://refactoring.guru/design-patterns/observer">here</a>.</p>
<p>The interface for tiny store is a simple one,</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> TinyStore&lt;T&gt; {
  get: <span class="hljs-function">() =&gt;</span> T;
  set: <span class="hljs-function">(<span class="hljs-params">value: T</span>) =&gt;</span> <span class="hljs-built_in">void</span>;
  subscribe: (callback: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">void</span>) =&gt; UnsubscribeFn;
  use: <span class="hljs-function">() =&gt;</span> T;
}

<span class="hljs-keyword">type</span> UnsubscribeFn = <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">void</span>
</code></pre>
<p>The <code>get</code> function will return the current value of the store, it can be called from anywhere, inside a React component or outside of it, but it will not trigger a re-render if used inside a React component. The <code>set</code> function will update the current value in the store and notify the subscribers. The <code>subscribe</code> function will allow listening for changes to the value of the store, it also returns an <code>unsubscribe</code> function that you can use to stop listening for changes. The <code>use</code> function is a React hook to get the value of a store in a React component.</p>
<p>Now, let write the function that will create the store, we will call it <code>createTinyStore</code>, it will take it an initial value and it will return an object of matching interface <code>TinyStore</code> .</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createTinyStore</span>&lt;<span class="hljs-title">T</span>&gt;(<span class="hljs-params">initialValue: T</span>): <span class="hljs-title">TinyStore</span>&lt;<span class="hljs-title">T</span>&gt; </span>{
    <span class="hljs-keyword">const</span> state = { value: initialValue }
    <span class="hljs-keyword">const</span> setState = <span class="hljs-function">(<span class="hljs-params">newValue: T</span>) =&gt;</span> {
        state.value = newValue
        notify()
    }

    <span class="hljs-keyword">const</span> subscribers = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>&lt;symbol, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">void</span>&gt;()
    <span class="hljs-keyword">const</span> notify = <span class="hljs-function">() =&gt;</span> subscribers.forEach(<span class="hljs-function"><span class="hljs-params">subscriber</span> =&gt;</span> subscriber())
    <span class="hljs-keyword">const</span> subscribe = (callback: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">void</span>) =&gt; {
        <span class="hljs-keyword">const</span> key = <span class="hljs-built_in">Symbol</span>()
        subscribers.set(key, callback)
        <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
            subscribers.delete(key)
        }
    }

    <span class="hljs-keyword">const</span> useHook = <span class="hljs-function">() =&gt;</span> useSyncExternalStore(subscribe, <span class="hljs-function">() =&gt;</span> state.value)

    <span class="hljs-keyword">return</span> {
        get: <span class="hljs-function">() =&gt;</span> state.value,
        set: setState,
        subscribe,
        use: useHook,
    }
}
</code></pre>
<p>The hook implementation uses React’s <code>useSyncExternalStore</code>, you can read more about it <a target="_blank" href="https://react.dev/reference/react/useSyncExternalStore">here</a>. This will allow you to access this from a React component and trigger re-rendering when the value of the store changes. I will explain how the <code>useSyncExternalStore</code> works in an upcoming article, follow this blog to get notification when I publish it.</p>
<p>Here is how you might use this in your app with a simple counter example</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// src/stores/counter.ts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> counterStore = createTinyStore(<span class="hljs-number">0</span>);



<span class="hljs-comment">// src/components/CounterDisplay.tsx</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CounterDisplay</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> count = counterStore.use();
  <span class="hljs-keyword">return</span> &lt;h1&gt;Count: {count}&lt;/h1&gt;;
} 

<span class="hljs-comment">// src/components/CounterButtons.tsx</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CounterButtons</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> count = counterStore.get
  <span class="hljs-keyword">const</span> increment = <span class="hljs-function">() =&gt;</span> counterCounter.set(count() + <span class="hljs-number">1</span>);
  <span class="hljs-keyword">const</span> decrement = <span class="hljs-function">() =&gt;</span> counterCounter.set(count() - <span class="hljs-number">1</span>);

  <span class="hljs-keyword">return</span> (
    &lt;div&gt;
      &lt;button onClick={increment}&gt;Increment&lt;/button&gt;
      &lt;button onClick={decrement}&gt;Decrement&lt;/button&gt;
    &lt;/div&gt;
  );
}


<span class="hljs-comment">// src/App.tsx</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    &lt;&gt;
      &lt;CounterDisplay /&gt;
      &lt;CounterButtons /&gt;
    &lt;/&gt;
  );
}
</code></pre>
<p>You can test this out below.</p>
<iframe src="https://stackblitz.com/edit/vitejs-vite-luzc2kkh?ctl=1&amp;embed=1&amp;file=src%2FApp.tsx" style="width:100%" height="300"></iframe>

<p>By using the <strong>observer pattern</strong> and the <code>useSyncExternalStore</code> hook, we've now built an atomic state management solution that efficiently manages and distributes state changes to any component that needs it. This provides a solid foundation for understanding how modern global state libraries function.</p>
<p>Tiny store is usable as it is, but you can expand on it by adding more functionalities. For example, you could add support for <strong>selectors</strong> to compute derived state, or build a layer for <strong>persistence</strong> to save state to local storage. You could also explore implementing Redux-style event dispatches with a state reducer for more complex applications.</p>
<h2 id="heading-further-reading">Further reading</h2>
<ol>
<li><p><a target="_blank" href="https://refactoring.guru/design-patterns/observer">Observer pattern - Refactoring guru</a></p>
</li>
<li><p><a target="_blank" href="https://react.dev/reference/react/useSyncExternalStore">useSyncExternalStore - React documentation</a></p>
</li>
</ol>
]]></content:encoded></item></channel></rss>