pp-share (Global Shared Reactivity)
pphp.share
creates a
global, reactive store that lives in the internal
__shared
namespace.
Any component can read and update it. Unlike state
,
a share is overridable at the app level, and there’s only one instance per key.
Use pphp.getShared(key)
to access a shared value anywhere
(without re-declaring), and you can observe changes with pphp.effect
.
Single source of truth: A share has exactly one instance per key in
__shared
.
Setting it anywhere overrides the value for the whole app.
API
public share<T>(
key: string,
initial?: T
): [(() => T) & { value: T }, (v: T | ((p: T) => T)) => void] {}
public getShared<T = any>(key: string): T &
((...args: any[]) => T) & {
set: (value: T | ((prev: T) => T)) => void;
} {}
public clearShare(key?: string): void {}
Parameters & Return Types
Function | Param | Type | Default | Description |
---|---|---|---|---|
share<T> |
key |
string |
— | Unique key for the shared value. Must be a non-empty string and not reserved. |
initial |
T |
— | Initial value when the shared key is first created. | |
Returns |
A tuple [getter, setter] where:
|
|||
getShared<T> |
key |
string |
— | Key of the shared value to read/update without re-declaring. |
Returns |
A callable reactive proxy that behaves like a getter function and object:
|
|||
clearShare |
key? |
string |
— | Delete one shared key (clearShare('user') ) or all (clearShare() ). |
Behavior & Guarantees
- Global & overridable: setting a share anywhere updates it everywhere.
- Single instance: a share lives in
__shared.<key>
. - Fast-path reuse: calling
pphp.share
again with the same key returns the same getter/setter. - Conflict warning: if a local
state
uses the same key in scope, a console warning is logged; the shared setter takes priority via the global key. - Reactive proxy from getShared: the returned value is callable and property-reactive, with a built-in
.set
. - Late binding: if a share isn’t ready yet,
getShared
performs short retry checks and updates dependencies once it appears.
Global override: Using the same key across app and components will override the value everywhere.
Choose explicit, descriptive keys to avoid collisions.
Use Cases
- Auth/session info shared across header, sidebar, and protected pages.
- Theme or layout toggles (dark mode, compact mode, RTL, etc.).
- Cart/checkout data reflected in multiple UI regions.
- Global notifications/snackbars and unread counters.
Basic Usage with share
<script>
// Declare (or reuse) a global counter
const [counter, setCounter] = pphp.share(0);
// Read in JS
console.log(counter()); // 0
console.log(counter.value); // 0
// Update globally
setCounter(p => p + 1);
</script>
<!-- In any template -->
<p>Counter: {{ counter }}</p> <!-- mustache works with the getter -->
<button class="btn btn-primary btn-sm" onclick="increment">+1</button>
<script>
function increment() {
setCounter(c => c + 1);
}
</script>
Access Anywhere with getShared
<script>
// No need to re-declare share; read/update from anywhere:
const user = pphp.getShared('user'); // callable reactive proxy
// Read:
console.log(user()); // full object or primitive
console.log(user.name); // reactive property access
// Update:
user.set(prev => ({ ...prev, name: 'Ada' }));
// or replace entirely:
user.set({ name: 'Grace', role: 'admin' });
</script>
<p>Hello, {{ user.name || 'Guest' }}</p>
Watching Changes with pphp.effect
<script>
// Observe updates on a shared key
const auth = pphp.getShared('auth');
pphp.effect(() => {
console.log('Auth changed:', auth()); // or auth.user, auth.token, etc.
}, ['auth']); // dependency can be the shared key string
</script>
Overriding a Shared Value (Global)
<script>
// Component A
const [theme, setTheme] = pphp.share({ mode: 'light' });
// Component B (later, anywhere):
const themeProxy = pphp.getShared('theme');
// This will override app-wide:
themeProxy.set({ mode: 'dark' }); // all places now read dark
</script>
Name collision: If a local
state
uses the same key as a
share
, the console logs a detailed warning (with scope info).
The global shared setter for that key will take precedence. Prefer distinct keys to avoid confusion.
Clearing Shared State
<script>
// Remove one shared key:
pphp.clearShare('user');
// Or wipe all shares (careful!):
pphp.clearShare();
</script>
Advanced: Shared Objects with Methods
You can store objects and mutate them via methods. Property access remains reactive,
and .set
can replace or update the whole object.
<script>
const [profile, setProfile] = pphp.share({
name: '',
age: 0,
set(data) {
this.name = data.name ?? this.name;
this.age = data.age ?? this.age;
},
reset() {
this.name = '';
this.age = 0;
}
});
// Elsewhere:
const sharedProfile = pphp.getShared('profile');
sharedProfile.set(p => ({ ...p, name: 'Jefferson' })); // updater
profile().set({ age: 29 }); // method on the object
</script>
<p>Name: {{ profile.name }} ({{ profile.age }})</p>
Tips:
- Use
pphp.effect(() => {...}, ['yourKey'])
to react to shared changes. - Reserved words are blocked for safety; choose descriptive keys.
getShared
gracefully binds even if the share is created later.