GithubHelp home page GithubHelp logo

magalhas / backbone-react-component Goto Github PK

View Code? Open in Web Editor NEW
810.0 810.0 72.0 1.41 MB

A bit of nifty glue that automatically plugs your Backbone models and collections into your React components, on the browser and server

Home Page: http://magalhas.github.io/backbone-react-component/

License: MIT License

JavaScript 100.00%

backbone-react-component's People

Contributors

bashmach avatar bmaland avatar bruno12mota avatar cranesandcaff avatar delantai avatar gfrivolt avatar hugoduraes avatar ieugen avatar jbhatab avatar jfschwarz avatar joaosamouco avatar larsonjj avatar magalhas avatar mainameiz avatar misumirize avatar oliviertassinari avatar pazzilivo avatar romanenko avatar tad-lispy avatar thomfoolery avatar zigomir avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

backbone-react-component's Issues

prepare for react 0.11

Backbone.React.Component may break due to private API usage (#16). Concerning Backbone.React.Component.mixin running the unit tests will probably suffice ๐Ÿ‘

All or nothing

Apparently you have to use the mixin on the absolute global root component or it doesn't work at all...

I'm having trouble rendering 3 components (all using the mixin) inside a common (React) container (not using the mixin).

I think it may be to do with the "Wrapper" only starting listeners on a root node, when I'm essentially trying to create 3 "root nodes" - meaning they all have a component._owner, and nothing ever satisfies the conditional to trigger the calls to this.startModelListeners() and this.startCollectionListeners()

Any ideas?

React mixin

what are your thoughts on making this a React mixin as opposed to a new extendable class object?

i think a new class object is a lot to swallow as it enforces a new API that is different from the traditional React API, and therefore breaks compatibility. could it be possible to add the functionality as a mixin and then write an additional wrapper for the new API?

an example of a similar, but not entirely up to par, mixin is https://github.com/tgriesser/backbone-reactview.

cheers!

How to use with collection `fetch`?

Hey Jose,

The examples in the README are very helpful, but all of the collection ones use a static array of model data. How does it work when the collection is loaded by calling fetch? I'm having trouble.

Here's what I have:

var User = Backbone.Model.extend({});

var Users = Backbone.Collection.extend({
  model: User,
  url: '/users.json'
});

var Child = React.createClass({
  mixins: [Backbone.React.Component.mixin],
  componentWillMount: function () {
    this.getCollection().fetch();
  },
  createRow: function (user) {
    return (
      <tr>
        <td>{user.name}</td>
        <td>{user.email}</td>
      </tr>
    );
  },
  render: function () {
    return (
      <table>
        <tr>
          <th>Name</th>
          <th>Email</th>
        </tr>
        {this.props.collection.map(this.createRow)}
      </table>
    );
  }
});

var Parent = React.createClass({
  componentWillMount: function () {
    this.users = new Users();
  },
  render: function () {
    return (
      <div>
        <Header />
        <Child collection={this.users} />
        <Footer />
      </div>
    );
  }
});

React.renderComponent(
  <Parent />,
  document.getElementById('container')
);

The table is rendered, the fetch is successful, but then render is never called after the collection sync event, so the table isn't updated. Which leads me to believe I'm calling fetch at the wrong point?

Thanks for any help you can provide!

Incoming on v0.8.0

Major

  • React v0.13
  • Internally @setState will be always used instead of @setProps, so you're model/collections data will be available under @state (#36, #54)
  • @getModel and @getCollection no longer crawls the dirty _owner reference (which will be removed on incoming React release), instead they are able to grab the model and collection instances through @context (new React feature)
  • When passing a single model, the JSON representation will be available under @state.model instead of directly into @state
  • New @overrideModel and @overrideCollection methods to programatically override a model/collection in a component. This is useful for use cases such as react-router (#60)

Minor

  • Listen to Backbone.Model#invalid event (#53)
  • @$ now fallbacks to DOM's querySelector if jQuery is not present

Bug fixes

  • Allow to change collection/model references (#29) (by filtering @componentWillReceiveProps)

Calling Backbone.Collection.fetch in componentDidMount triggers inconsistent number of renders

Assume we have a React component with the Backbone.React.Component mixin, and that the component takes in a Backbone collection as a prop.

If we call this.getCollection().fetch() in the componentDidMount function of the React component, it seems to trigger an inconsistent number of renders. Sometimes it renders a total of 2 times, and other times it renders a total of 3 times. I'm assuming this is due to an asynchronous issue?

Thanks so much!

demo screencast

Not 100% sure if this is the right place to ask this, but I was planning on making a screencast with this library. I was planning on making it using middleman + backbone + react and either a dummy api or a rails api that isn't shown in the screencast.

Do you have any ideas or concepts you think should make their way into the video? Also would you consider putting this in the readme?

Listen to 'invalid' event on a model

hi, I wonder if you could give me an example of how to listen to a backbone model's 'invalid' event within the component using this library. many thanks.

wrong sync collection => react

i click on remove Tag action (i class="icon-remove..") n-times, in situation when i remove all Tags models from collection and add new one i see problem like this

i click on (data-id=258)

<label data-reactid=".r[hy76].[4]"><span data-reactid=".r[hy76].[4].[0]">Tag 258</span><span data-reactid=".r[hy76].[4].[1]"><i data-id="258" class="icon-remove icon-white" data-reactid=".r[hy76].[4].[1].[0]"></i></span></label>

and onClick method are executed

_delete: function (e) {
      alert('delete data-id' + $(e.target).data('id'));
      this.getCollection().remove($(e.target).data('id'));
},

alert return message "delete data-id 11" ist old wrong id wichin i removed earlier.. its loiking like some data are unsynced with view.... any idea what can be wrong ?

remove, edit for blog eg.

i adding successfully new items to collection and react work gr8 with backbone thanks of backbone react component but what is bet way to remove, edit elements ? How can i get reference to clicked element and execute edit/remove action, it will be good to add fully CRUD to blog eg.

_index: function (item) {
      return (
        <label data-id={item.id}>{item.name} <span onClick={this._delete}>x</span></label>
      )
    },

    _delete: function (item) {
      this.getCollection().remove(this.$('label').data('id'));
    },

Not able to invoke any instance method

It looks like the backbone models and collections are serialized into their raw JSON form. Some data I'd like to render is the result if invoking instance methods I've defined on my model, but this.props.myMethod() does not exist.

Not to run render twice collection.fetch

I've simple React.Component and collection relation with your software.

I initialize empty collection, then try to fetch in in

componentDidMount() {
  this.getCollection().fetch({reset: true})
}

And your lib change state 3 times because two events fired in collection: request, reset, sync.

Sure I can do it like this:

    componentDidMount() {
      this.getCollection().fetch({
        reset: true,
        silent: true,
        success(collection) {
          collection.trigger('change');
        }
      });
    },

But please consider something, not to change state during collection fetch call so many times.

Or Am I doing something wrong ?

View props and model attributes out of sync

I can't seem to keep the React view props and model attributes in sync after an attribute as been 'set' on the model. .get('attributeName') on the model object (after using .getModel()) and .props.attributeName return the full attribute and undefined respectively. Any ideas on what may be going on?

Blog Example: toHTML() error

Right on the first line of Blog example you have error with

  res.send({
    component: blogComponent.toHTML(),
    data: blogCollection.toJSON()
  });

toHTML will return result to callback

Automatically set "key" ?

In all the examples, key is manually set on each component, but not in the README. Following the README yields this warning:

Each child in an array should have a unique "key" prop. Check the render method of MinerTable. See http://fb.me/react-warning-keys for more information.

It'd be nice if this library could automatically set key=model.id as a default that can be overridden.

Cannot read property 'setProps' of undefined

I've been using the component and it's been working great. However, I occasionally get the this error.

Cannot read property 'setProps' of undefined

It seems to happen when an event triggers setProps and the component is quickly unmounted, which deletes the component. The error is triggered here

Using React v0.10.0

Cannot read property 'on' of undefined

I keep getting this:

Cannot read property 'on' of undefined

when I run this:

/** @jsx React.DOM */
var MyComponent = Backbone.React.Component.extend({
  render: function () {
    return <div>{this.props.test}</div>;
  }
});
var model = new Backbone.Model();
var newComponent = new MyComponent({
  el: document.body,
  model: model
});

Overwritten views should update collections

I am mounting a new a React view constantly on the same DOM node, and until I was changing props it was all fine. Using a different collection causes there to be an inconsistency between .props.collection and .getCollection().

Using of fetch is ignored

I have a browserify/node kind of application and wanted to use this module to bind backbone collections/models to react components. Unfortunately when I call fetch() method on collection/model then component not listening for changes on sync events. The factory approach does not work in that case as I need a component body. I try to set props such as collections using setDefaultProps. Here is my example file:

"use strict";

var React         = require("react"),
    Router        = require("react-router"),
    $             = require("jquery"),
    _             = require("underscore"),
    Backbone      = require("backbone"),
    backboneMixin = require("backbone-react-component");

Backbone.$ = $;

var FieldModel = Backbone.Model.extend({
    idAttribute: "name"
});

var FieldsCollection = Backbone.Collection.extend({
    model: FieldModel,
    url: "/fake-api/fields.json",

    parse: function (response) {
        return response.fields;
    }
});

var Fields = React.createClass({
    mixins: [backboneMixin],

    getDefaultProps: function () {
        return {
            collection: {
                fields: new FieldsCollection()
            }
        };
    },

    componentDidMount: function () {
        this.getCollection().fields.fetch();
    },

    createEmptyRow: function () {
        console.warn("empty row");
        return "";
    },

    createFieldRow: function (field) {
        console.warn(field);
        return "";
    },

    createTable: function () {
        console.warn(this.props.fields);
        return (
            <div className="table-responsive">
                <table className="table table-striped table-bordered">
                    <thead>
                        <th>Row #</th>
                    </thead>
                    <tbody>
                        {this.props.fields.length === 0 ? this.createEmptyRow() : this.props.fields.map(this.createFieldRow)}
                    </tbody>
                </table>
            </div>
        );
    },

    render: function () {
        return (
            <div>
                {this.createTable()}
            </div>
        );
    }
});

module.exports = Fields;

How do collections flow down to children?

Let's say my app has a Dashboard โ†’ which contains projects โ†’ and each project contains posts.

Is this the intended structure?

DashboardView = React.createClass
    mixins: [...]
    getDefaultProps: ->
        collection: { projects: BackboneCollection }
    render: ->
        this.props.projects.map (project) ->
            <ProjectView model=project />  #1

ProjectView = React.createClass
    mixins: [...]
    render: ->
        <div>this.props.project_title</div> #2

... and so on?

There are two problems I'm facing. At #1, this.props.projects isn't the Backbone collection; it's just an array of objects that are props. So passing it as a model into ProjectView doesn't work.

At #2, I can access the Backbone model's attributes through props, but I can't access methods that I may have written for the model. Like project.findOverduePosts() or whatever. How do I access the pure Backbone model?

Correct way to listen for events

module.exports = React.createClass({
    mixins: [BackboneMixin],
    removeProduct: function(product){
        this.getCollection().products.remove(this.getCollection().products.findWhere({
            name: product.name
        }));
    },
    createProduct: function(product){
        return <li onClick={this.removeProduct.bind(this, product)}>{product.name}</li>;
    },
    render: function(){
        return (
            <p>PRODUCTS: <ul>{this.props.products.map(this.createProduct)}</ul></p>
        );
    }
});

When I remove the clicked Model from the passed in Collection instance, the UI does not seem to update. If you could confirm I'm using state/props, etc...correctly, that'd be marvellous.

Should clarify, the Model is successfully removed from the Collection.

update peer dependency on npm version

Version 0.6.5 that is published on npm has React set to version ^0.10.0 in both the peerDependencies and devDependencies.

Please publish a version that will work with version 0.11.0.

Using React's private API

This library is great but I notice it's using the __realComponentInstance property which was part of React's private API. In recent versions of React this property has been removed and certain functionality this library provides does not work anymore.

I was able to use this library with the latest version of React only if I use the mixins: [Backbone.React.Component.mixin] approach.

Bug: When using as a component, only the first child is passed on to the React component

When passing multiple children like this

var MyComponent = Backbone.React.Component.extend({
  render: function () {
    return <div>{this.props.children}</div>;
  }
});
var newComponent = new MyComponent({
  el: $('body')
}, React.DOM.p(null, "1"), React.DOM.p(null, "2"));

rendered HTML will look like this:

<div>
    <p>1</p>
</div>

for a fix see: https://github.com/jfschwarz/backbone-react-component/commit/798110fcb7217cdbf7bbbd8865989028438c2c5c

Not an issue, just wondering:

   //backbone-react-component.js:162
   this.component = component;
    // Start listeners if this is a root node and if there's DOM
    if (!component._owner && typeof document !== 'undefined') {
      this.startModelListeners();
      this.startCollectionListeners();
    }

Why only listen if it's a root node? Is there some performance tradeoff if it's a child node? I'm trying to have a dynamically rendered view with routing and this is kind of a puzzling requirement because I can't reset the model (outside the component once mounted). Thanks!

_owner getting deprecated in React v0.13

This will make code break for people relying on @getModel and @getCollection to get models and collections from parent components.

@getOwner will also be removed.

Still need to know how to distinguish an owner from an ownee in order to make changes for this incoming version.

Why does the mixin use props instead of state?

the state object is what React is designed to use with dynamic data sources. In fact in the documentation it states about this.setState:

This is the primary method you use to trigger UI updates from event handlers and server request callbacks.

Which is exactly how a model/collection binding would work. Why is this mixin going against the direction of the React documentation? Especially as props are supposed to be able to be accesses and changed by parent components - this seems against how you'd want to compartmentalize your code.

Question: is there any way to avoid initializing the model in the renderComponent?

So instead of doing it this way:

var MyComponent = React.createClass({
  mixins: [Backbone.React.Component.mixin],
  render: function () {
    return <div>{this.props.foo}</div>;
  }
});

var model = new Backbone.Model({foo: 'bar'});
React.renderComponent(<MyComponent model={model} />, document.body);

being able to do something like this:

var MyComponent = React.createClass({
  mixins: [Backbone.React.Component.mixin],
  model: new Backbone.Model(),
  render: function () {
    return <div>{this.props.foo}</div>;
  }
});

React.renderComponent(<MyComponent  />, document.body);

Class Extension Support Dropped in Upgrade?

I was using backbone-react-component to integrate React into our existing Backbone app, and really liked the class extension feature that this library implemented. Just trying to understand the reason it was dropped in the upgrade to React v0.11. Would love to continue using this library, but have setup many of my components to inherit from a base for ease of transition from our current Backbone structure to the new React components. Is there any part of it that's incompatible with the new React version or could this be added back in?

confused about the design pattern, re: usage of props vs. state

The usage of props seems at odds with the React documentation: http://facebook.github.io/react/docs/thinking-in-react.html

props are a way of passing data from parent to child ... State is reserved only for interactivity, that is, data that changes over time. Since this is a static version of the app you don't need it.

I think it's strange that all of the model's attributes are added directly to this.props. It doesn't seem like this is the use case React had in mind for props, and it pollutes that namespace. Moreover, you're creating more than one way to access the model attributes, via this.props.foo, and this.getModel().get('foo').

Child components using mixin do not auto-re-render on collection change

This has been tangentially addressed in the past. But I'm confused as to why a _child_ component - using Backbone.React.Component.mixin, and taking in a collection as a prop - doesn't seem to re-render itself when its collection changes (e.g. its collection was fetched, or a new model was added, or a model was deleted).

To elaborate on the above case, the collection would be instantiated _within_ some parent of said child component (e.g. in the parent's render or componentShouldMount function), and then _passed_ to the child as a prop.

The auto-re-rendering all seems to work fine when the mixin is added to any _topmost_ parent component (which is then rendered via React.render). Shouldn't it also work if it's included in any child component? This seems like a pretty commonly occurring scenario.

Thanks so much!

Provide alternative to mixin

Hello Jose,

I found an issue with react-backbone-component and react-router that made me think about looking for alternatives like RefluxJS and ditch the backbone stuff (I had a lot of bad experiences with Backbone in the past. They still come and haunt me :( ).

The problem is that the mixin does not get called when react-router changes the route, and the new route has the same path, but a different query param. The this.props.model is erased and the code breaks.

Reading the RefluxJs documentation on how to integrate with React [1] I found out that you can design backbone-react-component to be called programatically during the component life-cycles, and not as a mixin. That way, I can make sure that the integration works and I have full control. The mixin could be added as a convenience, similar to RefluxJs case, giving developers more freedom and more control.

I provided a gist showing my React view. Notice I build next and prevvious links by suppling query params. First rendering works, going for next/previous fails.

How hard would it be to do this in the current state of the project?

[1] https://github.com/spoike/refluxjs#react-component-example
[2] https://gist.github.com/ieugen/ca17c3463d26eddc07d5

Filtered collection

I'm not 100% sure if this is the place for this, but I'm just gonna post it to see what you all think.

I'm trying to filter a collection by a search term and then pass that down to a list. It gets filtered properly but when I call @getCollection() it gives me the original collection still.

RailsBox = React.createClass
  mixins: [Backbone.React.Component.mixin]

  getInitialState: ->
    { search_term: '' }

  setSearchFilter: (search_term) ->
    @setState(search_term: search_term)

  filteredRails: ->
    search_term = @state.search_term

    bb_rails = new Evue.Collections.Rails(@props.rails)

    # This successfully filters the collection
    filteredResults = bb_rails.bySearchTerm(@state.search_term)

  render: ->
    div {},
      Filters(setSearchFilter: @setSearchFilter)
      RailsList(collection: @filteredRails())


RailsList = React.createClass
  mixins: [Backbone.React.Component.mixin]

  render: ->
    # This is where the problem happens.
    # @getCollection() returns the original results
    # but @props.collection returns the filtered results
    # I want the filtered results in collection form.
    div className: 'list-group filter-list',
      @getCollection().map (rail) =>
        RailItem(model: rail, key: rail.get('id'))

I'm aware I can just pass the props down to the rail list, but I want to pass the collection the rails list and call getCollection() to get the filtered results. Any ideas on how to get this to work?

Update npm and bower

Integration with react router didn't work, just to realise that it was due to outdated version when installed via npm.

With the current version cloned from git, it works well with react-router. ๐Ÿ‘

Will this work on the server?

Really cool library! I'm intrigued.

Have you tested this to see if you could render a component to string on the server (node.js)?

It would be a really great way to render an initial collection server-side, then use the same components for client-side DOM updates.

getInitialState treats @getCollection() differently

I am making a mixin for sorting and trying to access @getCollection() in the getInitialState call. It keeps giving me this error, "Cannot read property 'collection' of undefined". What did work was using @props.collection, which returned the collection. Which is weird because props.collection generally returns just the json data.

But in the sortedData and sortBy functions, @getCollection() and @props.collection return to the original functionality.

So my question is what is @props.collection supposed to return and should I be able to do what I'm doing.

User collection

MyApp.Collections.Users = Backbone.Collection.extend
  url: 'http://jsonplaceholder.typicode.com/users'
  model: MyApp.Models.User

  sortAttribute: 'name'
  sortDirection: 1

Sort Mixin (what I think should work)

MyApp.Mixins.SortMixin =

  getInitialState: ->
    { sortAttribute: @getCollection().sortAttribute, sortDirection: @getCollection().sortDirection }

  sortBy: (attr)->
    newSortDirection = 1
    if @state.sortAttribute == attr
      newSortDirection = @state.sortDirection * -1

    @setState(sortAttribute: attr, sortDirection: newSortDirection)

  sortedData: ->

    filteredResults = @getCollection()

    filteredResults.sortDirection = @state.sortDirection
    filteredResults.sortBy(@state.sortAttribute)
    filteredResults


Sort Mixin (what actually worked)

MyApp.Mixins.SortMixin =

getInitialState: ->
{ sortAttribute: @props.collection.sortAttribute, sortDirection: @props.collection.sortDirection }

sortBy: (attr)->
newSortDirection = 1
if @state.sortAttribute == attr
newSortDirection = @state.sortDirection * -1

@setState(sortAttribute: attr, sortDirection: newSortDirection)

sortedData: ->

filteredResults = @getCollection()

filteredResults.sortDirection = @state.sortDirection
filteredResults.sortBy(@state.sortAttribute)
filteredResults

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.