If you'd like to try out the demo, follow these steps.
npm installnpm start- open your browser to [http://localhost:3000/demo]
As I've been learning about the Flux architecture I've been trying to build my own proof of concept. Flux is a pattern for application architectures and there are Flux implementations that are becoming more popular, like Redux. However, it's not as though Redux is the be-all and end-all of Flux. It requires some very specific trade-offs to be made for it to be properly leveraged. To be able to know whether or not these trade-offs are acceptable, you need to have a solid grasp of vanilla flux.
So, Plux is my effort at learning how Flux works and the pros and cons of different tradeoffs you can make while using Flux. Where a framework like Redux will allow you to have perfect playback and capture of an app's state, Plux offers flexibility to gradually ease into the Flux pattern. You may not need advanced features of Redux but you'll still want the benefits that Flux has to offer.
You can follow the proof-of-concept branch to see how Plux is implemented directly in the browser, without any tools or libraries. React is not required, and really it is not a prerequisite for any application using the Flux pattern.
Plux may never be released for general usage, but you can feel free to use the code in your own applications and tweak it to suit your purposes.
Shout out to @n1207n for patiently helping me get started with Flux.
The Plux API represents everything you get when you include/import plux into your project.
plux.createStore(storeName, function, [initialState])
Creates and registers a store with plux with the given storeName that will receive all actions that are executed. The function provided represents the action handler. It receives four arguments when an action is executed. action, data, state, and event.
actionis a string representation of the action that's been executed and dispatched to the store.datais argument that was included when the action was executed.stateis the state object associated with the store.eventis a function that must be called when the state has been modified. An optional argument can be provided that specifies a custom event name. By default, the event name ischange. Achangeevent will always be emitted if any event is emitted.
The optional initialState argument allows for a provided object to serve as the starting state for a store.
let actionHandler = function(action, data, state, event){
switch(action){
case "anAction":
state.count++;
event();
break;
}
};
let sharedStore = plux.createStore("shared", actionHandler, { 'count': 0 }); plux.subscribe(storeName, function, [event])
Creates a subscription to the store with the given storeName which executes a given callback function when a change event occurs. If the optional event argument is provided, then the callback will be executed only when the given event is emitted from the store. The callback function will include the arguments state and event.
staterepresents a shallow copy of the state associated with the store.eventis a string representation of the event that was emitted from the event handler.
The return value of the subscribe function is a subscription object.
plux.subscribe("shared", (state) => console.log(`The count is now ${state.count}.`));plux.listen(storeName, event, function)
Listen is almost identical to subscribe, but requires that an event be named for the subscription to be listened for.
plux.listen("shared", "incremented", (state) => console.log(`The count has been incremented to ${state.count}.`));plux.once(storeName, event, function)
Once is almost identical to listen except that it will only execute the callback one time and then unsubscribe from the store. This is meant to be a more convenient way of managing subscriptions that only care about one specific instance of an event, such as when a configuration is loaded. It returns a variable of a subscription object.
plux.once("shared", "initialized", (state) => console.log(`The count has been initialized to ${state.count}.`));plux.createAction(actionName)
createAction will generate a function that will dispatch the actionName to all stores. The generated function accepts one optional argument that will be passed as data to each store's action handler.
let sendMessage = plux.createAction("message");
sendMessage("Hello!");plux.getState(storeName)
getState returns a shallow copy of the current state associated with a name matching storeName.
plux.getState("shared");The Store API is used to interact with store objects returned from plux.createStore. While you cana do most of what you need to do through the plux API, this option is helpful when you want to be able to import stores or hold them in a variable. In addition, the Store API allows for advanced getters to be configured which provide ways to share common tasks when working with the store's state.
The string representation of name used to identify the store.
store.subscribe(function, [event])
Identical to plux.subscribe except that the store's name does not need to be provided.
myStore.subscribe((state) => console.log(`The count is now ${state.count}.`));store.listen(event, function)
Identical to plux.listen except that the store's name does not need to be provided.
myStore.listen("incremented", (state) => console.log(`The count has been incremented to ${state.count}.`));store.get([getter])
If an optional getter is not specified, the current state for the given store will be returned. If the getter is specified, then the store will return data from the state using the specified getter.
myStore.get('count');store.createGetter(getterName, function)
Creates a getter on the store with the given name and executes the provided function when the getter is requested. The getter function will be provided with the store's state.
myStore.createGetter("count", (state) => state.count);store.once(event, function)
Identical to plux.once except that the store's name does not need to be provided.
myStore.once("initialized", (state) => console.log(`The count has been initialized to ${state.count}.`));This API is returned when calling the subscribe or listen methods on plux or the store API. It's important to hold these references so that unecessary subscriptions are cleaned up. If you are using components, for example, it's important to unsubscribe from a store when a component is destroyed. Otherwise the risk of a memory leak is introduced.
A unique integer used to identify the subscription.
subscription.unsubscribe()
Removes the subscription from the store. It will no longer be notified of updates after unsubscribe has been called.
The name of the store that the subscription/listener is associated with.
The once API is almost the same as the subscription/listener API. The difference is just in the semantics.
subscription.cancel()
Identical to subscription.unsubscribe.