Connect Backbone Models and Collections to React.
const UserModel = Backbone.Model.extend(); const UserCollection = Backbone.Collection.extend({ model: UserModel }); const userInstance = new UserModel({ name: 'Harry', laughs: true }); const anotherUserInstance = new UserModel({ name: 'Samantha', laughs: false }); const userCollection = new UserCollection([userInstance, anotherUserInstance]); class MyComponent extends React.Component { render() { return ( <div> <p> My user laughs: {this.props.doesUserLaugh ? "yes" : "no"} </p> <button onClick={() => this.props.setUserLaughs(!this.props.doesUserLaugh)}> Toggle Laughing User </button> <h4>All Users</h4> <ul> {this.props.users.map(user => ( <li key={user.name}>{user.name}</li> ))} </ul> </div> ); } } // Maps Models to properties to give to the React Component. Optional. // Default behavior is to call `.toJSON()` on every Model and Collection. // Second argument are props given to the React Component. const mapModelsToProps = (models, props) => { const { user, allUsers } = models; const { showOnlyLaughingUsers } = props; // Everything returned from this function will be given as a prop to your Component. return { doesUserLaugh: user.get('laughs'), users: showOnlyLaughingUsers ? allUsers.toJSON().filter(user => user.laughs === true) : allUsers.toJSON(), setUserLaughs(newVal) { user.set('laughs', newVal); }, }; }; // Options. const options = { // Should our event handler function be wrapped in a debounce function // to prevent many re-renders. debounce: false, // or `true`, or a number that will be used in the debounce function. // Define what events you want to listen to on your Backbone Model or Collection // that will cause your React Component to re-render. // By default it's ['all'] for every Model and Collection given. events: { user: ['change:name', 'change:laughs'], // You can disable listening to events by passing in `false` or an empty array. }, // Define what modelTypes you expect to be contained on your `modelsMap` object. // Useful for validating that you'll be given what model type you expect. // Uses instanceof, and throws an error if instanceof returns false. // By default no modelTypes are defined. modelTypes: { user: UserModel, allUsers: UserCollection, }, }; const { connectBackboneToReact } = require('connect-backbone-to-react'); // Create our Connected Higher order Component (HOC). const MyComponentConnected = connectBackboneToReact(mapModelsToProps, options)(MyComponent);
Now that you've created your HOC you can use it!
// Map your Backbone Model and Collections to names that will be provided to // your mapModelsToProps function. const modelsMap = { user: userInstance, allUsers: userCollection, }; ReactDOM.render( // Pass the modelsMap to the HOC via the models prop. <MyComponentConnected models={modelsMap} showOnlyLaughingUsers={true} />, document.getElementById('app') );
Alternatively you might have a tree of connected Components. We shouldn't pass that modelsMap
object from one component to another. Instead we can take inspiration from react-redux's Provider component.
const { BackboneProvider } = require('connect-backbone-to-react'); const modelsMap = { user: userInstance, allUsers: userCollection, }, ReactDOM.render( // Pass the modelsMap to the BackboneProvider via the models prop. // It will then get shared to every child connected component via React's context. <BackboneProvider models={modelsMap}> <MyComponentConnected> <MyComponentConnected /> </MyComponentConnected> </BackboneProvider>, document.getElementById('app') );
This library's focus is on sharing Backbone.Models with React Components. It is not concerned with how to render React Components within Backbone.Views. The React docs provide a possible implementation for this interopt.
Apache 2.0