You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a proposal for a breaking change to Satchel — this would be Satchel v5. The goal here is to get rid of the two great evils in the existing implementation: global objects and side effects.
Motivation
Today Satchel's internal state — including stores, subscriptions, middleware, etc. — is stored in a global object hanging off the window. Mutators and orchestrators are registered by applying the mutator and orchestrator "decorators" to the handlers. (These APIs aren't really decorators — typically a decorator would just wrap the function in a higher order function — because they aren't wrapping the function but rather registering the function as a callback in the Satchel dispatcher.) This makes for very convenient coding patterns, but it presents some problems:
If there are multiple instances of Satchel on a page — for instance if some imported library or component also uses Satchel — then there may be conflicts within the store or configuration.
Because mutators and orchestrators are registered as side effects (the registration happens as part of code that runs at module scope) tools like Webpack have trouble applying optimizations like tree shaking to Satchel projects.
Proposal
Create satchel instances with createSatchel
Instead of assuming there's a global store available, consumers will create an instance of a satchel. There can be multiple satchels, configured separately and completely isolated in terms of data and subscribers — but in practice a codebase should only ever create one.
The options would include the middleware, replacing the applyMiddleware API. (I don't think there are any other options at this point.)
Explicitly register subscribers
Subscribers (mutators and orchestrators) must be explicitly registered on the satchel. Now mutator and orchestrator will be true decorators — they'll just wrap the handler in an object to be registered separately.
The mutator and orchestrator APIs will simply return an object with some properties. (If we care to keep the properties private we might encapsulate them in a closure and return that.) The properties will include:
The action to subscribe to
The callback
Whether it is a mutator or orchestrator (or, alternately, we could have separate registerMutator and registerOrchestrator APIs on the satchel, but I think just register is cleaner. We could also call it subscribe — thoughts?)
A flag indicating whether it has already been registered. Registering the same subscriber subsequent times is no-op. (We don't want the same subscriber get registered multiple times.)
Other APIs
Now that satchel is instanced, various other APIs will need to be changed:
mutatorAction will need to take in the satchel as an agument so that it knows where to register the mutator
dispatch will become a method on the satchel
action will become a method on a satchel so that it knows where to dispatch the action
getRootStore will become a method on the satchel
Add a satchel.hasSubscribers(action) API
This will allow consumers to check if there are any subscribers for an action. While not strictly necessary, this will be useful for middleware that wants to know if the dispatched action is handled by anything.
The text was updated successfully, but these errors were encountered:
This is a proposal for a breaking change to Satchel — this would be Satchel v5. The goal here is to get rid of the two great evils in the existing implementation: global objects and side effects.
Motivation
Today Satchel's internal state — including stores, subscriptions, middleware, etc. — is stored in a global object hanging off the window. Mutators and orchestrators are registered by applying the
mutator
andorchestrator
"decorators" to the handlers. (These APIs aren't really decorators — typically a decorator would just wrap the function in a higher order function — because they aren't wrapping the function but rather registering the function as a callback in the Satchel dispatcher.) This makes for very convenient coding patterns, but it presents some problems:Proposal
Create satchel instances with
createSatchel
Instead of assuming there's a global store available, consumers will create an instance of a satchel. There can be multiple satchels, configured separately and completely isolated in terms of data and subscribers — but in practice a codebase should only ever create one.
The
options
would include the middleware, replacing theapplyMiddleware
API. (I don't think there are any other options at this point.)Explicitly register subscribers
Subscribers (mutators and orchestrators) must be explicitly registered on the satchel. Now
mutator
andorchestrator
will be true decorators — they'll just wrap the handler in an object to be registered separately.The
mutator
andorchestrator
APIs will simply return an object with some properties. (If we care to keep the properties private we might encapsulate them in a closure and return that.) The properties will include:registerMutator
andregisterOrchestrator
APIs on the satchel, but I think justregister
is cleaner. We could also call itsubscribe
— thoughts?)Other APIs
Now that satchel is instanced, various other APIs will need to be changed:
mutatorAction
will need to take in the satchel as an agument so that it knows where to register the mutatordispatch
will become a method on the satchelaction
will become a method on a satchel so that it knows where to dispatch the actiongetRootStore
will become a method on the satchelAdd a
satchel.hasSubscribers(action)
APIThis will allow consumers to check if there are any subscribers for an action. While not strictly necessary, this will be useful for middleware that wants to know if the dispatched action is handled by anything.
The text was updated successfully, but these errors were encountered: