1) Which JavaScript hashchange/history library/method should I use for my JavaScript application?
2) And how do I achieve these 3 things using that method?
A) When the page loads I want to parse the url hash/parameters and set the initial application state.
Specifically, my application consists of a Backbone Collection with two models which has attributes such as selectedCountry, selectedYear etc.
(I don't think I can use the Backbone.Router as this is a very customized visualization app with complex states?)
B) I want to set up a hashchange listener or similar that lets me update the app state correspondigly
C) On Backbone Collection change events I'd like to update the url. Important: I want to remove the hashchange listener temporarily while doing this so that there is no feedback loop.
Note:
The app is already relying on some HTML5 technologies so the solution does not have to be compatible with the older browsers ... But the "feedback loop" part is important as I've struggled with this before ...
Thanks :)
since your already using Backbone, I would stick with Backbone's Router objects. It will be easier to use what's already available in your app instead of trying to bring something new in the mix.
As for your feedback loop problem, I've solved this by never firing my router methods from code.
The gist of it is that I let my JavaScript objects control the state of the application, and do the work for me. When I do call router.navigate, I never pass true as the second argument. I only call router.navigate in response to a state change in my app, to update the hash fragment in my browser window. Here's the thing: This is purely a response to the state of the application having changed. I never use router.navigate to change the state of my app.
Hope that helps
Related
I'm working on a narrow cast that displays an amount of tickets (an integer with the total added up to eachother) from a 3rd party API. I want to display a notification when this amount increases. I've read about mutationobservers, and that they are good for doing similar tasks like when something gets added or deleted.
The app has a Vue frontend, and a Laravel backend which does the requesting/authenticating. The index blade loads in a Vue component which contains the other components (and distributes the data from the API to child components).
I'm not quite sure wether mutationobservers are good for this specific job, though. Googling really didn't give me great alternatives.
In conclusion, I want to know if mutationobservers are the right tools for this task and what property would work. Better suited alternatives are also welcome.
Using vue, you can use a watcher function to watch for changes in a particular variable (amount). Mutation Observers only watches for dom updates, it won't give you what you want
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.
I'm writing a react/redux app that has a Job object that fires Events from time to time. On these Events the user is expected to react. I can easily write the React component that shows such a job or events, but don't know where to put the logic when
the user is not on the Job page
and an Event happens
and I would like to pop up a notification
Of course, once I get access to the store, I can create the notification too.
Shall I handle such logic in a React container that render() nothing?
Or handle it with vanilla JS when I load a Job data?
Or to handle it in the reducer when the data is stored? (probably not recommended)
My problem with the option two is that I don't know how to access the redux store from a totally ad-hoc code, as my store is not a global object.
What do you recommend?
Generally speaking, the two places that you'd put code that needs to access the store (for either dispatching or receiving state updates) is in middleware or a connected component. If you specifically want to respond to an action coming through, then you would need to use middleware.
I actually threw together a sample timer middleware in a chat discussion a few weeks ago. I just pasted it as a gist here as an example: https://gist.github.com/markerikson/ca96a82d6fdb29388aca4052a9455431 . Illustrates the idea of doing something asynchronously in the background.
You may also want to look through the list of middlewares in my Redux addons catalog: https://github.com/markerikson/redux-ecosystem-links/blob/master/middleware.md . Numerous examples of ways to execute background-ish logic.
Finally, https://github.com/yelouafi/redux-saga (which is itself a middleware) is a fairly common lib used to do background-ish logic.
I'm looking into mobservable but I'm having some trouble coming up with a good model to do url routing.
Because of how mobservable works with React using a standard react-router does nothing when you change the url. Only if we crudely pass the url path down into the Handler stack to make them reactive do I see some changes.
I feel this needs a different approach. Of course I could hack some custom thing but I kinda like react-routers way of nesting the urls and the solid Location/Link features.
I'm working a (non public) project that uses both mobservable and react-router. That setup is basically as follows:
Create all your routes, but give them all the same handler, your root component.
Introduce reactive state that stores your ui state (like, currently open document for example)
in the router.run callback, use the data that is passed in (the second argument) to update your ui state and to kick off the necessary data retrieval and such. In the end of the callback, just render your handler. Depending on your further setup of the root component you want to pass it the ui state or nothing at all.
For us that setup worked fine so far, so please let me know if you run into any trouble.
EDIT
Another setup using Director can be found in the Mobservable TodoMVC example
Linking this because I found it helpful. I am basically following the approach out here: https://github.com/contacts-mvc/mobx-react-typescript/blob/master/src/components/ContactDetails/index.tsx.
Initialize the store/model in the app's index page or wherever the routes are defined. Then pass the initialized store to the component. Inside the component componentWillMount grab the ID off the route and pass it to a function to load your data.
If you already had data loaded then make a method that changes the selected item. Make sure that select item property is observed and it should automatically update the UI. I think that is what #mweststrate means by UI state.
I have a question regarding Backbone JS's Models. I've already delved into Backbone JS quite a bit the last few days. I am understanding it now (and thanks to Stackoverflow, I have understood further with a few things).
At present, my web app is using Backbone Models to store dynamic navigation and other such bits. Stuff that is generally used in Backbone Collections. At present, my web app is still needing to store sort of 'global' states... Such as what the user has currently selected in the navigation (which then effects other parts of the app etc.)
I've been keeping all of these stored 'states' in variables like this:
App.data.selectedPage = whatever etc.
But I'm thinking more about Backbone Models... Should I be storing these 'global states' in a Model? Is that something that the Models can be used for?
At present, the webapp doesn't save to the server, or local storage, it's more of a converted Flash presentation I have to code for an iPad. So it still made sense to use something like Backbone for code organisation purposes... I mean, that's ok too right? To use Backbone, even I don't intend on storing the models anywhere?
Anyhow, yes, using models to store this sort of information is ok too? Anything goes? ...please do tell me if I'm approaching this wrong.
Many, many thanks.
James
I think one good rule of thumb for using backbone model is if you need events when some data is changing.
For exemple, you have a calendar with a selected date. Many other parts (views) of your app needs to know and be informed about the selected date. Then it makes sense to store the date in a model and have everyone listen on events from the calendar.
This is more for data related functions. For state it is different. Your selected page is a state to me. Page selection, page state, globals, they should be in your controllers. They (or it) should know what the state of the page is and they can trigger event when it changes.
Model => data centric with events