Documentation Index
Fetch the complete documentation index at: https://mintlify.com/smogon/pokemon-showdown-client/llms.txt
Use this file to discover all available pages before exploring further.
PSModel<T> is the lightweight observable at the heart of Pokémon Showdown’s reactive architecture. Every major piece of client state — the connection, preferences, teams, and the global PS object itself — is either a PSModel or extends one. Rather than relying on a virtual-DOM diffing library to decide what has changed, PSModel gives you fine-grained subscriptions: you ask to be told when something updates, and you get called directly. This makes it easy to integrate with Preact components, plain event handlers, or any other code that needs to react to data changes.
Unlike React’s usual immutable-data paradigm, PS Models are mutable. Mutations happen first; then
update() is called to notify all subscribers. Do not call update() before the mutation is complete.PSSubscription<T>
Every call tosubscribe or subscribeAndRun returns a PSSubscription<T>. Hold on to this object so you can unsubscribe later.
Properties
The model this subscription belongs to. Used internally by
unsubscribe() to locate and remove the subscription from the model’s list.The callback function that was passed to
subscribe or subscribeAndRun. Called every time the model’s update() method fires.Methods
Removes this subscription from its parent observable. Safe to call multiple times — if the subscription has already been removed the call is a no-op.
PSModel<T>
T = null) where update() is called without arguments to signal a state change. Pass a type argument to send a value along with each notification.
Properties
The live list of all active subscriptions for this model. Managed automatically by
subscribe() and PSSubscription.unsubscribe(). Iterate over this array yourself only if you need to inspect or bulk-remove subscriptions.Methods
Registers a listener function and returns a
PSSubscription handle. The listener is not called immediately — it will be called the next time update() fires.Combines
subscribe with an immediate first call to the listener. Useful for initialising UI state without duplicating the render logic.No-value overload. Declared as
update(this: PSModel): void — available on any PSModel instance, regardless of T. Notifies every subscriber by calling their listener with undefined (cast to T internally via value!). Use this when the interesting information is the mutation itself, not a specific value.Value overload. Notifies every subscriber, passing
value to each listener.Usage Examples
Preact Component Integration
The standard integration pattern for Preact (used throughout the PS client) is to subscribe in
componentDidMount and unsubscribe in componentWillUnmount. This matches the component lifecycle and avoids memory leaks from stale subscriptions.How PSModel Fits in the Architecture
PSModel vs PSStreamModel
PSModel vs PSStreamModel
PSModel and PSStreamModel share almost identical APIs, but they differ in one important way: PSModel does not keep a backlog of past events. If you call update(value) before anyone has subscribed, that value is lost. Use PSStreamModel whenever events can arrive before listeners are ready — for example, server messages that arrive during page load.The global PS object
The global PS object
PS itself extends PSModel (with no type argument, so T = null). Calling PS.update() is the standard way to trigger a re-render of all top-level Preact panels. Individual models like PS.prefs, PS.teams, and PS.user have their own subscription trees for more targeted updates.