I’m once again exploring using Redux within Meteor/React, something that’s been a stumbling block for me before. But I’m on a project using React Native, so I decided to take another shot at Redux, and this time it clicked! (the caffeine must’ve helped…)
Anyway, I’m wondering how one goes about wiring in Mongo collections and other reactive variables into container components with Redux. Is the ReactMeteorData mixin not used? If you map Redux state to props using React-Redux’s connect:
function mapStateToProps({user}) {
return {user}
}
export default connect(mapStateToProps)(ContainerComponent)
then does it make sense to check for Redux state changes and call dispatch within componentWillReceiveProps, since this kind of logic doesn’t belong in render?
componentWillReceiveProps(nextProps) {
if (nextProps.user.someCondition) {
dispatch(someReduxAction());
}
}
render() {
if (!this.props.user.loggedIn) {
return <div>Log in, please!</div>
}
return <div> ... </div>
}
Did you read Abi’s posts? https://medium.com/@abhiaiyer
It has some insights on how to approach things, maybe it’s for you, maybe not…
Have you checked Adam’s flux-helpers? https://github.com/AdamBrodzinski/meteor-flux-helpers
I keep referring back to it, because it’s really easy to begin with things and think about possible problems later (I mean, it’s easy to get a proof of concept running, don’t worry about the redux store vs minimongo). Maybe @SkinnyGeek1010 has some tips as well, since he has experience with React Native also if I’m not mistaken.
What is the use case? Maybe you don’t even need de lifecycle hooks in this case? Perhaps something else can call the action for example?
Also, but it’s more a personal preference, I like to move dispatch actions to props as well, with mapDispatchToProps from react-redux. This way you even more decouple redux with the components.
In simple apps I just let Minimongo take care of data and use getMeteorData for mongo data and Redux for everything else.
However, it can be helpful to have all data in one tree as it can be more simple to keep track in your head. The easiest way i’ve found is to use the flux helpers I made and dispatch a ‘collection changed’ event. Then you basically just read from the collection and return that as the new state. In essence you’re just mirroring Minimongo whenever it changes it’s data. This means you never have to worry about manually updating/removing/inserting data… it just works.
There is a memory cost to this of course and it can make your Redux more complicated (by just a bit). I just have a collections reducer that switches on the collection name and they sync data. I also have a viewer collection that basically watches Meteor.user()
Here’s the gist (from the package):
Tracker.autorun(computation => {
var docs = Players.find({}).fetch();
if (computation.firstRun) return; // ignore first empty run
CollectionActions.playersChanged(docs);
});
Ok. But on a very basic level, I was just wondering: if getMeteorData is the place one listens for changes in Mongo collections and ReactiveDicts, then where does one listen to changes in the Redux state? Of course render is the place if it’s determining whether to display something or not based on Redux state. But what about when you want to dispatch an action? That’s why I figured componentWillReceiveProps might make sense, since Redux state changes come into the React container in the form of props.
Action creators should only return an action object of format {type: 'SOME_ACTION'[, ...other properties]}, and shouldn’t perform any actions such as fetch(), db operations, etc. For that, use a thunk?
Redux-Thunk provides you dispatch and getState to use in the returning function:
export function simpleAction() {
return {
type: "SOME ACTION"
}
}
export function thunkAction() {
return (dispatch, getState) => {
Meteor.call((error, res)=>{
dispatch(simpleAction());
})
}
}
Some tips:
dispatch not only can dispatch other actions but also other thunk actions as well
getState is a function not a variable, because you want to make sure you have the latest state, if you are dispatching AFTER a remote call, the state might have changed since the start of the call, and if you want to dispatch depending on the currents state, you should do
const state = getState();
What happens to the Optimistic UI Meteor offers if we do asynchronous calls? Doesn’t it cause delay on the UI because of waiting for the result to arrive?