AdamBrodzinski / meteor-flux-leaderboard

Flux Example with React & Meteor
131 stars 19 forks source link

Redux sample improvement? #9

Open SenerDemiral opened 8 years ago

SenerDemiral commented 8 years ago

AppContainer.jsx

function mapDispatchToProps(dispatch) {
  return Redux.bindActionCreators(Actions, dispatch);
};

AppContainer = connect(mapStateToProps, mapDispatchToProps)(AppContainer);

in Player.jsx (and others), no need to define handleClick(), just call dispatch on onClick (should be function)

PlayerItem = React.createClass({
  getClassName() {
    var selectedId = this.props.selectedPlayerId;
    var playerId = this.props.player._id;
    return (selectedId === playerId) ? 'player selected' : 'player';
  },

  render() {
    var player = this.props.player;
    return (
      <li className={ this.getClassName() } 
          onClick={ () => this.props.selectPlayer(this.props.player._id) }>
        <span className="name">{ player.name }</span>
        <span className="score">{ player.score }</span>
      </li>
    );
  }
});

Even JedWatson/classnames also helpfull.

AdamBrodzinski commented 8 years ago

Thanks! I agree that it's more terse but I would like to keep it as simple and explicit as possible for someone who's looking at it the first time.

I would accept a PR for an advanced redux branch though, that way it's clear that it's not the most simple way to do things.

:beers:

genyded commented 8 years ago

Along these line, it would also be nice in the advanced branch to show some examples of tracking the current user (viewer), actually handling some crud operations so we can see how/if to tie into Meteor methods, routing to more than one component for an example of how best to handle that... and so on.

The ReactiveStack doesn't (yet) bring flux into the mix, but does just about everything else under the sun and includes the basics for just about everything in their still fairly simple example.

AdamBrodzinski commented 8 years ago

@genyded agreed! I'm hoping to have some free time this weekend (like literally 2 hours lol) and I might be able to push something.

I'm currently just watching the users collection with the flux helpers and dispatching a change when the Meteor.userId changes (along with the Meteor.user data). I've also opted to use a viewer key to make it more clear that the user data is for the user viewing the site.

For crud actions, I just use Meteor methods for models like in my reactive-meteor project (on GH) and I call those in the action creator like this:

export function createPost(data) {
  Meteor.call('Post.create', data, (err, res) => {
    if (err) return dispatch(showError(err.reason))
    dispatch({ type: 'CREATE_POST', loading: false })
  });

  return {
    type: 'CREATE_POST',
    loading: true,
  };
}

Note that i'm not actually returning any data here because the meteor method/model is doing a db.posts.insert(...) and when the model inserts the collection changes. Since I have the flux helpers dispatching any change, this data will be instantly in minimongo.

Any error means it will be taken out of mini mongo and again another action will be dispatched to keep the redux store in sync (for when optimistic updates fail).

This example is also using a loading indicator in case that's helpful, but not required.

Does this make sense?

genyded commented 8 years ago

Mostly... still getting my head around flux in general, let alone a specific 'flavor' and every little bit helps. I know Meteor pretty well and react, but gluing it into this abstracted state is still somewhat of a blur.

Not yet entirely clear on where subscriptions should go, and if I have a component that needs multiple 'subscriptions' how does that map (before I just returned each as an object key from MeteorData). All the examples i find only have one simple Todo or Leaderboard subscription.

Also how do you determine how best to split up reducers or when - again the examples only have one which gives me no idea. I'll get it after I spend a bit more time 'playing' and every bit I can see and touch helps so thanks for this and trying to make it more detailed!

AdamBrodzinski commented 8 years ago

Not yet entirely clear on where subscriptions should go,

The convention in React is to use a 'view controller' normally named 'container'. It's job is to gather data and pass it down as props. For example a PostsContainer will just subscribe to data and use connect with Redux to get the data (perhaps in the collection.posts key in the redux store). It's only other job is to render Posts and pass this data down to it.

Once the subscription adds the data to minimongo it will trigger dispatches that 'posts' collection has changed and that starts the whole re-render. This allows PostsContainer to declaratively say to Redux... whenever state.collections.posts re-render and i'll pass it down to Posts.

and if I have a component that needs multiple 'subscriptions' how does that map (before I just returned each as an object key from MeteorData). All the examples i find only have one simple Todo or Leaderboard subscription.

You can just subscribe to multiple things at once, no worries there.

Also how do you determine how best to split up reducers or when - again the examples only have one which gives me no idea. I'll get it after I spend a bit more time 'playing' and every bit I can see and touch helps so thanks for this and trying to make it more detailed!

In general you want as few as you can without having too much code to scroll through. Having one reducer is fine for small apps but having 200 lines it way too much. Normally I make a reducer for each 'domain' in my app. You can also make one for each data 'resource' too (collection). The key is to make as many as needed to make your life easier.

looshi commented 8 years ago

Great example app! I'm brand new to Redux, this is really helpful. At the bottom of the Redux branch readme, it calls out 'Key pieces are in CollectionActions/Store..' but after some digging around, I think all of that has been moved over to skinnygeek1010:flux-helpers ? If so , might be good to call out this helper package earlier in the readme.

AdamBrodzinski commented 8 years ago

@looshi ah good catch! you're right I ended up creating the package from those files. I should prob. also add a section on the readme to exlplain that more. I'll try to get this done in the next week or two (PRs welcome :wink: )

looshi commented 8 years ago

@AdamBrodzinski I made a branch which uses methods instead of pub/sub : https://github.com/looshi/meteor-flux-leaderboard/tree/redux-methods

I don't know how to create a pull request for a new branch, but it would be cool to have a methods example in your suite of examples here. The idea is keep the redux branch as it is, but add a new branch which does the same thing via methods.

I ran into some issues and confusion when dealing optimistic UI. I just kind of went with instinct for now, I'm interested to see what others think about this branch, then update it with feedback.

My branch may be too different in terms of versions for you to want to deal with it -- I updated meteor, then wound up snowballing into updating tons of things. One other minor thing is this redux-methods branch has an example of setting up the newer version of Redux DevTools with browserify, I might be doing it totally wrong, but got it to work.