I've been using backbone.js
for most of my frontend JavaScript projects so far, but after hearing about Facebook's react.js
I got interested and started poking around.
I'm wondering whether or not I'm supposed to use the Backbone.View
class anymore or replace every "view" with a react "component" - even the "base-view" that's layouting the page ...
I found some posts in the interwebs that still used Backbone.View
s - others I stumbled upon only created React-classes.
Maybe someone can point me in the right direction ... what to use when and how to best implement multiple "pages/states" in single page app and not just the usual (I can stand it anymore) TODO example.
Here some code that I came up with:
Backbone init stuff:
require(
[
"jsx!app/view/base",
"react",
"app/router",
"backbone"
],
function (BaseView, React, Router, Backbone) {
"use strict";
var router = new Router();
var base = new BaseView({router: router});
React.renderComponent(base, document.getElementById("page"));
router.on("route", function(action) {
base.setProps({path: action});
});
Backbone.history.start({pushState: true});
}
);
app/router
:
define(function(require) {
"use strict";
var Backbone = require("backbone");
/**
*
*/
var Router = Backbone.Router.extend({
routes: {
"": "home",
"test": "test",
"*error": "404"
}
}); // end Router
return Router;
});
app/view/base.jsx
:
define(function(require) {
"use strict";
var React = require("react");
var mixins = require("app/utils/mixins");
var Header = require("jsx!app/view/header");
var ContentHome = require("jsx!app/view/content_home");
var ContentTest = require("jsx!app/view/content_test");
var ContentLogin = require("jsx!app/view/content_login");
/**
*
*/
var BaseView = React.createClass({
render: function() {
var content;
switch (this.props.path) {
case "home":
content = <ContentHome />
break;
case "test":
content = <ContentTest />
break;
case "login":
content = <ContentLogin />
break;
case "404":
default:
content = "Error, page not found";
break;
}
return (
<div id="base" onClick={this.onClick}>
<Header />
{content}
</div>
);
},
onClick: function(event) {
if (event.target.tagName.toLowerCase() === "a" &&
event.target.className === "main") {
event.preventDefault();
this.props.router.navigate(event.target.pathname, {trigger: true});
}
}
}); // end BaseView
return BaseView;
});
But I'm not completely pleased with this setup. Any input is welcome.
React is great for single page applications because it allows developers to create applications that are mobile first and responsive. React allows developers to create applications that are fast and easy to update, which is great for mobile applications.
Backbone. js is a model view controller (MVC) Web application framework that provides structure to JavaScript-heavy applications. This is done by supplying models with custom events and key-value binding, views using declarative event handling and collections with a rich application programming interface (API).
Backend Synchronization BackboneJS is use with the front-end and back-end systems, allows the synchronization with the backend to provide support to RESTful APIs.
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;
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With