Flux stores changing other stores - javascript

I'm creating an app with Flux and React, which is kinda of a game... and this app has 3 stores:
GameStore -> contains the game status like finished, how many times the player won, and this stuff
CounterStore -> Is a countdown store that is self triggered every 1 second, and the counter component updates itself.
BlockStore -> this is related to the game componentes, which are kinda of blocks that the user can interact on.
So, whenever I click on a Block, I trigger an action and get it on the BlockStore. The BlockStore does some magic and identifies if the block clicked was correct, if it was, it updates the GameStore (with how many times the user clicked on the correct block) and updates the CounterStore (which increases the timer for the user).
Also, whenever the CounterStore gets to 0, it also changes the GameStore to set that the user has lost.
This feels totally wrong, my stores they are connected somehow... Each action changes almost all of the stores, but some actions depends on the store result, to change the other stores (that's confusing :S).
I want to get a opinion whether I'm doing it in the right way, maybe I should place everything in one store (which will make it hard to maintain), or remove some stores and treat some stuff as a component state directly (the counter for example).
I'm lost here.

Pulled from https://facebook.github.io/flux/docs/overview.html :
Stores contain the application state and logic. Their role is somewhat
similar to a model in a traditional MVC, but they manage the state of
many objects — they do not represent a single record of data like ORM
models do. Nor are they the same as Backbone's collections. More than
simply managing a collection of ORM-style objects, stores manage the
application state for a particular domain within the application.
Your GameStore should should not be holding information for each block. The BlockStore should be holding the blocks and the data pertaining to the individual blocks. Since you have other data that describes the overall state of the game, I would recommend having a second store that is dedicated to holding that state (ie. a StateStore that would hold the counter, in-play/finished, score, etc).

Related

Passing values between components: Pass References vs Subjects

tl;dr: Why not pass variables by reference between components to have them work on the same data instead of using e.g. BehaviorSubjects?
I'm writing a sort of diary application in Angular 8. I have two components (Navbar and Dashboard) and a service (EntryService).
Navbar lists the entries, Dashboard provides the textarea, EntryService glues them together and communicates with the database.
While debugging the application I stumbled upon a way to communicate between the service and a component that i haven't thought of before.
By accident I passed a variable (entry: Entry) from the Dashboard by reference to the EntryService. The service saved to the database getting a unique ID back and saving this ID into the entry variable. This change immediately reflected to the Dashboard because of the 'passing by reference'.
Until now I was using Subjects to update the components on changes, but passing references around seems to be much simpler, because I want to work on the same data on both components and the service.
I've studied Angular for a while now and not read about this approach, so I'm wondering if it is a bad idea or design and if yes why?
Thanks for your answers!
Passing by reference can be handy. But as a general approach to keep the application components in sync it has some draw backs. With Subjects you can easily investigate in which places of the application the value of the Subject will be changed by checking where the Subject.next() function is being called. When you pass your object by reference to a hundred components/services it will be much more difficult to find out, which of them modify the object and more importantly when, becaue often you want to trigger other changes afterwards. When you subscribe to Subjects, you get notifications about changes and can react to them. Subjects and Subscribers are an example for an Observer/Observable pattern, it allows you to decouple your application logic. And they are much more flexible, for example you can have a Subject which can return the last x number of changes or you can debounce the changes when you track user input, you can apply filters to them etc.

Incrementing variable in action creator

I was recently watching Dan Abramov redux series and one episode got me really curios. In this episode - Redux: Extracting Action Creators, timecode: 00:32~1:32 he's making action creator as a separate function (like it would normally look in the typical redux application) because:
... However, what if another component wants to dispatch the add todo
action? It would need to have the access to next todo ID somehow
But is that actually making any sense? In that particular example, nextTodoId variable (which is always incrementing) is available to all components inside that jsbin even if we don't extract action creator into a function.
Even if we'll imagine that it will be in a separate file (action creator), on each import that variable will be equal to the initial value (0) which breaks it's uniqueness concept.
So, what does he meant by that? How is that approach (of making action creators as a separate functions) will guarantee us the acccess to that next todo id variable?
You're focusing on the wrong aspect. It's a fair enough point that this is a terrible way to store "current ID", but that isn't the purpose of the refactor he is showing.
The real purpose is that Components should be as agnostic about their context as possible. A Component trying to "addTodo" really shouldn't be concerned with "what is the current max todo ID?".
In contrast, the actionCreator is concerned with this aspect. It takes in data from the components and is then responsible for translating it to a dispatchable call that has real value.

Component Entity System Entity Specific Data

I've been writing a Component Entity System in javascript for a while now but I keep returning to a root issue.
How do you handle entity specific - that is to say a single instance or single type - functionality?
Here's the current situation:
The way I have structured things, when an item entity is stored in inventory by another entity it isn't destroyed, merely stripped of most of its components. This is so that if it is dropped, or perhaps retrieved for use, it can be reactivated with its old state. The components that are stripped are stored in an InstanceDataComponent attached to the entity (this is just a JSON object).
There is a small system for managing the internals of whether an item can be picked up and adding an inventory record with a hash, quantity, and id for the thing being stored but something needs to manage the transformation of that entity from its "item" state to its "stored" state. What should do this? It seems to me that the details of which component to remove and what data to alter will need to be nearly unique for each item.
Suppose that in the future I want an entity to switch between two behaviors on the fly. For example, to pace to and fro until it is disturbed then pathfind to the player. What will handle that transition?
I get the feeling I've got a fundamental misunderstanding of the issues and typical architecture here. What would be a clean way to handle this? Should I perhaps add a component for each set of behavior transitions? Wouldn't that end up with far too many components that are glorified callback wrappers? Or am I missing something about how an entity should be altered when it is stored in inventory?
Some thoughts for others who might be going through this situation.
My current solution (after several iterations) is to fire a global event e.g. itemPickupSystem:storedItem and an entity can attach handlers for any events inside its factory method. This isn't scalable, for a number of reasons. I've been considering moving those events into a queue to be executed later.
My factory methods have turned into a hodgepodge of callback definitions and things are degrading into callback hell. In addition, this events system has to go, it is the only part of the entire system that breaks the serial nature of the game loop. Until now each system fired in a defined order and all logic resided inside those systems. Now I can't guarantee that an entity will be in a specific state because those callbacks could have been fired at different points. Finally, because execution is being turned over carte blanche to code that isn't part of the core functionality there is no way to know how large that call stack will get when an event is fired.
Sometimes it's easiest to think of this problem in terms of pragmatic network replication, and the boundaries between components come naturally.
Let's say that your actor can both wield, and store, a sword.
I would not anticipate a 'transform' from an inventorySword into a presentationSword, but rather that there's a natural delineation between an 'inventoryItem' and a 'swordPresentation'.
On the server, each player would be assigned a list of items in their inventory. Each item would have a unique id for the world. The inventory item might be derived as 'SwordItem' and have properties for SwordType and Condition%
On the client, a 'swordPresentation' component might handle the job of which mesh to display, which socket to attach animation data to when displayed via a 1st person camera, and how to smooth animation transitions. But none of that matters to the actual state of the game, it's simply how our client is seeing the world.
Potentially, if you were distributing the state of the game to each client all that you would pass over the network would be the current player's inventory, and for the other players, which item each player has currently equipped and where they are (assuming they're in eyesight)
So, consider creating a factory that creates a 'swordPresentation' based off of an inventory item, finding the bare minimum you can pass in as parameters to create a representation of the component (maybe it's sword type, sword % condition, etc).
Whatever that bare minimum is what you want to serialize as your inventory item.
Establishing a clear delineation between replicated data means better performance, fewer vulnerabilities when you're writing a multiplayer game. When you're writing a single-player game, it'll help you understand what goes into a save file.

Flux - Stores' data lifecycle

There's one thing about Flux (or at least about its implementations) that I don't quite understand.
It's about internal data management of Stores. I'll try to explain my question by breaking it down into points.
Let's imagine I have some app with client-side routing.
As I understood Stores are singletons. Somewhere they store some data (e.g. an array)
User clicks somewhere and navigates to some part of the app. Correspoding Store fetches some data.
Let's imagine that it's a really big amount of data. So big that it takes a lot of resources and even makes page laggy.
After a while user navigates to a different route. What happens with the internal data of the Store mentioned above?
As far as I understood, it remains intact. At least until user navigates to original route and the Store changes its state.
And before that happens the Store holds big amount of data even when it's not needed.
Can someone clear this out for me? Thanks.
Store just listen the dispatcher(actions) and somehow react on it. In example you mention - yes, it will hold the data at least you don't use weakmap or kinda, but you also can listen actions on changing routes and process your data in this case.

What if two Flux stores have to depend on each other

One of the goals of Flux is to make the app more predictable by reducing crazy tangled dependencies. Using the Dispatcher you can define a strict order in which the Stores are updated. That creates a nice tree dependency hierarchy. That's the theory. Consider following situation:
I have a game. The store sitting at the top of the hierarchy is StateStore that holds only the current game state, i. e. playing, paused, over. It is updated via actions like PAUSE or RESUME. All other stores depend on this one. So when a store handles some kind of update action (i. e. MOVE_LEFT), it first checks the StateStore and if the game is paused or over, it ignores the action.
Now let's say that there is an action that would cause game over. It updates some store and the store decides that the game shouldn't continue ("the game character moves left and falls into a trap"). So the state in the StateStore should change to over. How do I do that?
Theoretically, it should go like this:
The given store is updated first and reaches the point of game over
The StateStore is updated afterwards (it waitsFor the other store), checks the other store and switches the state to over.
Unfortunately, the other store needs to access the StateStore as well to check the current game state to see if it should be updated at all (i. e. the game is not paused). They clearly depend on each other.
Possible solutions:
Merge such stores into one store. That would probably cause my whole app to collapse into a single store which brings up the question whether Flux in this case is a good idea.
Distinguish update order and read-only dependencies. All stores would be updated in a strict order, however they could read from each other arbitrarily. The StateStore would therefore for every action check all existing stores and if any of them indicated game over, it would change the state to over, effectively preventing all other stores from updating.
What do you think?
In Flux stores should be as independent from each other as possible and should not read from each other. The only way to change their state is through actions.
In your case, if some store decides that the game is over — you should update a StateStore from the ActionCreator. You can do it by calling a HaltGameActionCreator from the store or by dispatching a HALT_GAME action from ActionCreator that triggered the store change in the first place.
For those having the same issue, you can read here about the actual application I had this problem with and how I approached it. Long story short, I allowed all the stores to arbitrarily read from each other (the suggested solution no. 2).
Note that ES6 modules allow circular dependencies which simplifies the implementation.
Nevertheless, looking back I'm not sure if it was a right decision. If a piece of business logic inherently contains a circular dependency, we should not try to apply a solution that doesn't really support it just because somebody says so. Flux is only one pattern, there are many other ways how to structure the code. So perhaps I would recommend collapsing the whole logic into a single store and use one of the other ways to implement the store itself (e.g. standard OOP techniques).
I would also consider using redux with reselect instead of Flux. The problem with the original example is with the StateStore that depends on two different inputs. It can be changed either by the user explicitly pausing/resuming the game, or by the game situation reaching game over. The advantage of this approach is that you need to check only one store to get the current game state.
With redux/reselect, you'd have one reducer handling pause/resume actions and another reducer handling the game situation. Then you'd have a selector combining these two pieces of information into the final game state. Most of the business logic would be moved from the stores to action creators, i.e., in the moveLeft() action creator, you'd use this selector to check the game state and only then you'd dispatch MOVE_LEFT action.
Note that this is just a rough idea and I don't know if it's viable.

Categories

Resources