Also here’s a slightly more complex example with something similar I just did… take data from the cordova contacts data structure and reformat it to work in my app. This means using different keys, filtering contacts without a phone number, and formatting the number so Twilio wouldn’t complain.
Here’s a similar example using the above methods. Note some use inline anonymous functions and others pass in a function from a utils library:
There’s a nice js functional library that might help some. The library is called Ramdajs. I find the functions to be a bit more powerful than underscore and lodash; more importantly, taking a functional approach has elevated my approach structuring problems.
You can certainly handle it in a container with getMeteorData. The easiest way is to use the flux helpers package. You can then just call:
// watch the logged in user and trigger an action on change
trackViewer(CollectionActions.viewerChanged);
Any time the Meteor.user() data changes this will call any function passed in… ideally a Redux action.
If you need more fine grained control your could listen for a change and then call like this:
// in client code
Meteor.startup(function() {
Tracker.autorun(function(computation) {
var user = Meteor.users.find(Meteor.userId(), {fields: {"profile.foo": 1}})
if (computation.firstRun) {
return; // ignore first empty run
}
// call your action creator here
CollectionActions.viewerChanged(user);
});
});
}
This is a pretty simple setup and you could wonder why you need Meteor at all, besides the easy setup of the backend and scaffolding of course that Meteor offers.
You might consider having @SkinnyGeek1010 flux-helpers on the side for auto updates of the store;
Have you looked at this? You could argue about having two stores on the client. But overall I have a better experience with it for example when updating the database not from the client (e.g. you want to mark a todo as checked for a general list not owned by 1 user).
I haven’t run into problems with it (that it’s out of sync), but I didn’t make a giant app or anything.
@rolf That’s actually kind of what I was going for, making it easier to move to a different backend by centralizing all the logic / client-server interaction. I didn’t list that as a feature because I haven’t actually tried to do it, so I’m not sure if there are any huge edge cases.
// track the maxIndex and presenterIndex from the server
export function trackPresenter (id) {
return Tracker.autorun(function (computation) {
let show = Shows.findOne({_id: id})
// update the store
dispatch(setPresenter(show.presenterIndex))
dispatch(setMax(show.maxIndex))
if (show.ownerId === Meteor.userId()){
// set the current slide to presenterIndex if current user is the presenter
dispatch(setSlide(show.presenterIndex))
}
})
}
So theoretically we could just change trackPresenter() to use socket.io or something else without actually modifying the jsx. It’s also much more modular. And if tracker runs unnecessarily, we can do a deepEquals here and not actually dispatch any changes. Or we can dispatch conditionally with other checks like if(…=== Meteor.userId())
Can you give a couple examples of how you use actions in your templates? Are you saying they essentially call ActionCreators in redux which then call out to your Meteor methods?
What do you mean by this:
UI States on top of things pulled down from a Meteor publication. We made a reactive store essentially a reactive-dict, to use this state in our components.
You have a separate reactive store outside of Redux? Not following…
Do you actually use Redux lib or just emulate the pattern?
It seems that we could store a redux-like state on Session and it would persist through hot code reload and be similar. But maybe that’s crazy?
@rolf, thanks for your reply.
I´m looking for a simple solution, that puts Meteor as my backend, and react as the frontend.
That´s not only for the case I want to change the backend, I feel that the code became much more clear this way.
@dfischer, the idea is to use just Redux inside components. You get somehow the data you need from Meteor, and dispatch it to the store.
From your component, you just subscribe to this data, and use it like in a regular redux app.
I was thinking about a Tracker function, but the official packege is actual very simple, and I love official stuff…
That´s way I´m using an empty component, just to get meteor data and send to redux´s store.
Using redux for data doesn’t make much sense to me as that overlaps too much with minimongo. However using it just for ephemeral state + action dispatch seems like a nice separation of concerns.
If any data is coming through a subscription then I wouldn’t touch that with redux.
I was just about to post a link to this - we’ve just been working through it, it’s an excellent set of posts, thank you for taking the time to write it.
@yinghao , that seems like a good structure to me. For the sake of discussion and learning I made this example that uses DDP directly instead of minimongo and tracker.
It’s really easy to update the store from the incoming DDP messages. I think this is still very ‘meteoric’, even though it may sidestep some of the meteor front-end features.
Great article, thanks for posting this. Is workpop fully transferred to React now? I saw the job posting for recat /full stack front end guy. You guys are doing awesome stuff there. I’m working on building my skillsets to working for a company like yours someday
It ends right when it gets to actions - Is that where you draw the line? Make the mutations through actions otherwise the rootReducer will pick up the dispatch message? So for mutations you dispatch a function, and for UI state you dispatch a TYPE?
Do you guys use one file for all actions or actions per a module?
edit: nvm there’s more (blog post 3 doesn’t link to the next one fyi)