What if two Flux stores have to depend on each other - javascript

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.

Related

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.

ReactJS local vs global state and implementing redux at a later time

So we are about two months in on a project. This is the first time I have ever managed code writers and not written the code myself. I've been reading their code for the last week. What was suppose to be a simple React app has turned into a spaghetti mess.
I understand: redux helps to manage global state. But should that mean that all buttons should map to a global "action?" This has seemed to create this entire mess of objects scattered throughout the entire app. I keep asking myself, why are we using global state for everything when local state could be used for 90% of the application. This is the kind of code that gives me heartburn:
let subitems = SidebarItems[state.type].sub_items;
Store.dispatch(SidebarSubItemHandler(item.action, subitems[0], null));
if(item.sub_items[subitems[0]].param) {
browserHistory.push(`${item.sub_items[subitems[0]].path}/${item.sub_items[subitems[0]].param}`);
} else {
browserHistory.push(item.sub_items[subitems[0]].path);
}
subItembuttons = Object.keys(this.props.subitems.sub_items).map(subitem => {
let subItem = this.props.subitems.sub_items[subitem];
return <li className={this.props.activeSubItem.action == subItem.action ? "bottom-bar-item active" : "bottom-bar-item"}
onClick={e => this.props.onClickSubItem(e, subItem)}
key={subItem.action} style={this.props.subitems.inlineStyles.mobileSubItemLI}>
{subItem.item}
</li>;
});
The application is littered with all kinds of objects like these that map to "action" objects. So at this point we are making the decision to scrap the entire project and restart from scratch, but without redux. Let's try to do as much as possible using local state only. When it comes time, and we need global state for something, ONLY implement it for that something, not every single action in the app. Does this make sense?
So I guess my question is: If we develop an app using local state and just fundamental React, will we be creating un-reversable problems that would prevent us from implementing redux on a per item basis?
Quoting from the relevant Redux FAQ entry at http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-only-redux-state:
Using local component state is fine. As a developer, it is your job to determine what kinds of state make up your application, and where each piece of state should live. Find a balance that works for you, and go with it.
Some common rules of thumb for determing what kind of data should be put into Redux:
Do other parts of the application care about this data?
Do you need to be able to create further derived data based on this original data?
Is the same data being used to drive multiple components?
Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)?
Do you want to cache the data (ie, use what's in state if it's already there instead of re-requesting it)?
Per your specific question: if you use the "container component" pattern fairly consistently, it should be relatively straightforward to swap those "plain React" containers for Redux-connected containers down the line. See https://github.com/markerikson/react-redux-links/blob/master/react-component-patterns.md#component-categories for articles on the "container/presentational component" pattern.
Two other thoughts. First, I recently co-authored an article that discusses why you might want to use Redux in a React application.
Second: yeah, that code looks kinda ugly. I'm hoping those are at least three different snippets from different parts of the codebase, rather than one snippet, but that's rather hard to read. The repeated use of "sub_items" and "subitems" seems like a bit of a red flag, readability-wise.
It also doesn't look like it's following good Redux practices. For example, idiomatic Redux code almost never references the store directly. Instead, references to dispatch and getState are available via middleware, and thus can be used in action creators via redux-thunk and redux-saga. Connected components can also access dispatch.
Overall: you are absolutely welcome to use as much or as little Redux as you want, and as much or as little local component state as you want. I think the larger issue, though, is how well your team actually understands Redux, and how they're trying to use it.

Dispatching actions via a callback in Redux

I'm working on building an step sequencer in Redux to help me learning. What I need is some universal clock that functions as "tick" to provide musical timing.
So I planed to use the Tone.js library, which builds on top of the Web Audio API.
There's the following function:
Tone.Transport.scheduleRepeat(function(time){
//do something with the time
}, "8n");
You provide a callback function which gets called everytime the transport reaches a certain position.
My naive approach was to let the callback dispatch an action which increments a tick count in my store.
This doesn't work because actions have to be plain objects.
What are the possibilities to get this working?
I'm still working on getting the right understanding of the basic underlying principles of Redux so I'm unsure about that but could I somehow
catch the callback using middleware and just let it through when it is actually invoked?
Would this be the right direction? What are some libraries, examples or concepts I could look into to get some idea how this could be done?
Is this even the right direction or should I approach this differently? If so, how?
Or do you maybe have any idea what's the best way to provide global timing for different components in a Redux app?
I went into a lot more detail in https://www.html5rocks.com/en/tutorials/audio/scheduling/, but in short - you shouldn't use Javascript callbacks for musical timing. It's not accurate enough. That's why we have web audio scheduling.
Very interesting question, that's a pet project I've been also wanting to tackle but haven't written a single LOC yet. :)
For the timing part, you could use a middleware for that, or even a <Clock /> component that launches the scheduler itself and dispatches an action on every tick (probably with the time as payload).
The tricky part however is the overall design of your application. Having researched Tone.js a little bit, it was clear to me that you'd have to separate the audio part from the visuals. Which means your Redux state should only be concerned about representing your step sequencer (I'm visualizing something like a list of lanes (channels/instruments) and your audio logic should be kept outside of it.
I would keep an array of lanes, each of which is itself an array of "steps" that define whether they're "active" or not. Again this is only UI related. Clicking on a step to activate it should modify your state via action creator and also setup anything you'll later need to play with Tone.js.
When playing back your song, you'll need to dispatch that clock tick to advance the current active "step" so you can highlight it in the UI.
Here's a mouth-watering Codepen emulating a Roland TR-808 to grab ideas:
http://codepen.io/pixelass/details/adyLPR
And here's the relevant section on the Tone.js wiki on sync'ing audio and UI:
https://github.com/Tonejs/Tone.js/wiki/Performance#syncing-visuals
Sorry I can't help you further, perhaps you're ahead of me and already have some working code you could share.
Basically cwilso responded correctly. If you want to be scheduling JS functions for musical timing, you should not be using callbacks.
If there is Tone.js functionality that you want to implement based on this timing, avoid Redux and call these Tone.js functions directly, either within the callback functions or Tone.Transport.schedule function.
If you are building a sequencer I would recommend looping the Tone.Transport based on the length you want and scheduling the notes to be hit at certain points on the timeline (if this is what you are looking for). Check out the loopStart and loopEnd in the docs for help (http://tonejs.github.io/docs/#Transport).
If this functionality is necessary for visual references, which may be why you want a Redux callback, I can provide an example of how you might do that below:
function incrementTick() {
return { type: 'INCREMENT_TICK' }
}
// inside your component once the increment function has been connected
Tone.Transport.scheduleRepeat((time) => {
this.props.incrementTick()
}, "8n");
Hope this helps.
I'm working on an audio related application and have run into the issue of managing the web audio API part along with redux as well.
The way I've solved it is only storing representation of the audio state in the redux store (plain JS objects; what you would store in the database and use to initialize the app). This stored information is used to render the UI.
I have a service 'engine' class which listens to all changes in the store, this is where all the web audio stuff is created and stored. It contains basically a copy of the reducers from the redux store but applies the changes to the web audio nodes.
For example I dispatch an action:
{type:"set-gain", payload:{trackid:3, value:0.7} }
The redux store will simply update a plain JS track object to the new gain value, the engine will find the associated gain node (or create with add etc.) and set the value on it.
In your case you would dispatch an action to set the timing, in the redux store save it as plain JS object, in the engine part you use web audio scheduling to set it.

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 changing other stores

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).

Categories

Resources