structure of a Backbone and React single page app
Don't hold a reference to a component like you are. If needed use refs or better yet, just render the component in the callback. React will check if it needs to update the DOM.
require( [ "jsx!app/view/base", "react", "backbone" ], function (BaseView, React, Backbone) { "use strict"; var router = Backbone.Router.extend({ routes: { "": "home", "test": "test", "login": "login", "*error": "404" } }).on('route', function(action) { React.renderComponent( <BaseView router={router} path={action} />, document.getElementById("page") ); }); Backbone.history.start({pushState: true}); });
Edit:Since the logic in BaseView
is very coupeld to the logic in Router
, it makes most sense to keep them in the same file.
var BaseView = React.createClass({ render: function() { return ( <div id="base" onClick={this.onClick}> <Header /> {this.props.children} </div> ); }, onClick: function(event) { if (event.target.tagName.toLowerCase() !== "a") return; if (event.target.className !== "main") return; event.preventDefault(); this.props.router.navigate(event.target.pathname, {trigger: true}); }});
app/router:
var router = Backbone.Router.extend({ routes: { "": "home", "test": "test", "login": "login", "*error": "404" }}).on('route', function(action) { var pathMapping = { "home": ContentHome, "test": ContentTest, "login": ContentLogin }; var Content = pathMapping[action] || Content404; React.renderComponent( <BaseView router={router}> <Content /> </BaseView>, document.getElementById("page") );});Backbone.history.start({pushState: true});
var BaseView = React.createClass({ pathToComponent: function(){ var paths = { 'home': ContentHome, 'login': ContentLogin }; return paths[path] || Content404 }, render: function() { var ContentComponent = this.pathToComponent(this.props.path); return ( <div id="base" onClick={this.onClick}> <Header /> <ContentComponent /> </div> ); }, }); // end BaseView return BaseView;});