clayallsopp / react.backbone

Plugin for React to make Backbone migration easier
MIT License
840 stars 60 forks source link

Use with react-router #30

Open thomporter opened 9 years ago

thomporter commented 9 years ago

I'm trying to find a good way to use this with react-router. It works wonderfully at the collection level, but I'm not sure how I could set the model on the detail routes, short of hacking them in...

Here's some code:

// exports models & collections related to contacts
var db = require('./stores/app-contacts'); 
contacts.fetch();

React.renderComponent(
  <Routes location="history">
    <Route path="/"  handler={App}>
      <DefaultRoute name="home" handler={Home} />
      <Route name="contacts" handler={Contacts} collection={contacts}>
        <Route name="contact" 
                     path="/contacts/:userId" 
                     handler={ContactDetail}
                     model={?????} />
        <NotFoundRoute handler={ContactNotFound}/>
      </Route>
    </Route>
    <NotFoundRoute handler={NotFound}/>
  </Routes>,
  document.getElementById('main'));

Any ideas?

EtienneLem commented 9 years ago

I see two ways you can achieve that:

Option 1

It really depends whether you have access to userId outside of a component or not. From what I can see you can use ContactDetail#props.params.userId, but what you really need is the variable before mounting the component.

I’ve never tried react-router, but from the doc I can’t really see a way to do that. Is there a global object with all the current route params?

If you can get that variable, you’d only need to model={contacts.get(userId)}.

Option 2

Send the collection to the model component instead of the (unknown) model:

<Route name="contact" 
  path="/contacts/:userId" 
  handler={ContactDetail}
  collection={contacts} />

Then you subscribe with the modelOrCollection key:

var ContactDetail = React.createBackboneClass({
  mixins: [
    React.BackboneMixin({
      modelOrCollection: function(props) {
        return props.collection.get(props.params.userId)
      }
    })
  ]
})

Does it make sense? I haven’t tested it, but I think it would work.

thomporter commented 9 years ago

Makes sense. I think option 1 is a no go... I'm not seeing a way to pass that userId in. Pity, it's a more elegant solution. I may post something in the react-router repo about it.

Option 2 shows some promise, but the mixin ins't firing for me, any ideas why?

var ContactDetail = React.createBackboneClass({
  mixins: [  React.BackboneMixin({
      modelOrCollection: function(props) {
        console.log('modelOrCollection', props); // <-- Never fires
        return props.collection.get(props.params.userId)
      }
    })
  ],
  render: function() {
    var m = this.getModel(); // <-- returns undefined
    m = this.props.collection.get(this.props.params.userId); // <-- works, but is it a good idea?
    console.log(m);
    return (
      <div>
        {m.get('first_name')}
      </div>
    );
  }

});

As a side note, I'm looking at flux-react and flux-react-router now too.