martyjs / marty

A Javascript library for state management in React applications
http://martyjs.org
MIT License
1.09k stars 76 forks source link

Problem using container #228

Closed bigardone closed 9 years ago

bigardone commented 9 years ago

Hi! I'm trying to use the new containers for version 0.9.1 but I'm having some problems to do it. I have the following component:

class @PeopleSection extends React.Component
  constructor: (params) ->
    super params

    @displayName = 'PeopleSection'

  _renderPeople: ()->
    if @props.people.length > 0
      @props.people.map (person) ->
        `<PersonCard key={person.id} {...person}/>`
    else
      `<div className="warning">
        <h4>No people found...</h4>
      </div>`

  render: ->
    `<div>
      <div className="cards-wrapper">
        {this._renderPeople()}
      </div>
    </div>`

And this container:

Marty.createContainer PeopleSection,
  listenTo: PeopleStore

  fetch:
    people: ->
      PeopleStore.for(@).findPeople()

  failed: (errors) ->
    `<div className="warning">{errors}</div>`

  pending: ->
    `<div className="warning">Searching...</div>`

But I'm getting this error in the _renderPeople method:

Uncaught TypeError: Cannot read property 'length' of undefined

So it seems like the container is not working as it should. Is there anything else I have to do in order to use the container properly? Thanks in advance!

jhollingworth commented 9 years ago

Hey, I think this actually down to react no longer autobinding functions in v0.13. Could you try changing your constructor to

 constructor: (params) ->
    super params

    @displayName = 'PeopleSection'
    @_renderPeople = @_renderPeople.bind(this)

Or using React.createClass

bigardone commented 9 years ago

It didn't work :( Switching to React.createClass throws the same error. While debugging this corresponds to the PeopleSection component but the props attribute is empty so @props.people.length throws the error. I guess it has something to do with the way I have implemented the container or Rails's asset pipeline as is not fetching for the people.

chrisbarmonde commented 9 years ago

It could be useful to see the implementation of findPeople.

bigardone commented 9 years ago

@chrisbarmonde sure! here it is:

class @PeopleStore extends Marty.Store
  constructor: (options)->
    super options

    @displayName = 'PeopleStore'

    @state =
      meta:
        total_pages: 0
        current_page: 0

  findPeople: (pageNumber, searchText) ->
    @fetch
      id: 'all-people'
      locally: () ->
        @state.people
      remotely: () ->
        PeopleAPI.findPeople(pageNumber, searchText)

  receivePeople: (response) ->
    @setState
      people: response.people
      meta: response.meta
quazzie commented 9 years ago

Perhaps same problem as me #229 ? Props didn't get updated.

jhollingworth commented 9 years ago

Can you try updating to v0.9.2, @quazzie's fix to updating props has just been released

bigardone commented 9 years ago

Hi! I have upgraded to v0.9.2 and I've changed my project so I can use webpack and reproduce modules and requiring functionality. I'm almost there but it seems that it's not registering correctly the state sources.

Here's the state source:

Marty = require 'marty'

PeopleAPI = Marty.createStateSource
  id: 'PeopleAPI'
  type: 'http'

  findPeople: (pageNumber, searchText) ->
    req =
      url: Routes.people_path(
        page: pageNumber
        search: searchText
      )

    @get(req)

module.export = PeopleAPI

Here's the store:

Marty = require 'marty'
PeopleConstants = require '../constants/people_constants'
PeopleAPI = require '../sources/people_api'
PeopleQueries = require '../queries/people_queries'

PeopleStore = Marty.createStore
  id: 'PeopleStore'
  displayName: 'PeopleStore'

  getInitialState: ->
    meta:
      total_pages: 0
      current_page: 0

  handlers:
    receivePeople: PeopleConstants.RECEIVE_PEOPLE

  findPeople: (pageNumber, searchText) ->
    @.fetch
      id: 'all-people'
      locally: () ->
        @state.people
      remotely: () ->
        PeopleQueries.findPeople(pageNumber, searchText)

  paginationMeta: ->
    @state.meta

  receivePeople: (response) ->
    @setState
      people: response.people
      meta: response.meta

module.exports = PeopleStore

And here's the query:

Marty = require 'marty'
PeopleAPI = require '../sources/people_api'
PeopleConstants = require '../constants/people_constants'

PeopleQueries = Marty.createQueries
  id: 'PeopleQueries'

  findPeople: (pageNumber, searchText)->
    debugger

    PeopleAPI.findPeople(pageNumber, searchText)
    .then (res) ->
      console.log res
    .catch (err) ->
      console.log 'err'

module.exports = PeopleQueries

When trying to fetch remotely it throws an undefined is not a function error when calling PeopleAPI.findPeople. Debugging there shows that PeopleAPI is an empty object: Object {}. This also occurs when using the PeopleAPI from an action creator. Can this be a bug or I'm simply doing it wrong?

jhollingworth commented 9 years ago

That sounds like you have a circular reference. I'm going to try and replicate this locally and get back to you

bigardone commented 9 years ago

@jhollingworth thank you very much! Do you want me to share the repo so you can check the source?

jhollingworth commented 9 years ago

yeah, that would be amazing, thanks

bigardone commented 9 years ago

Here it is,

https://github.com/bigardone/rails_and_flux/tree/feature/webpack

Is still wip so there might be other issues I haven't resolved yet.

jhollingworth commented 9 years ago

Hey, this should fix it https://github.com/bigardone/rails_and_flux/pull/1

bigardone commented 9 years ago

wow @jhollingworth thank you so much for your time, shame on me for not seeing that before, now the error is gone :)

jhollingworth commented 9 years ago

No problem, happy to help