0

I want to show a list of messages when the page is loaded. i call action and addChangeListener to subscribe for changes in componentDidMount, hoping i can get the data back from server from store, though addChangeListener is called, but the callback is not being invoked. It seems like this.on('change', callback) in store is not working as it should. does anyone know what is the issue of my code? Im following the example on flux's repo

Also, where is the proper place to make api calls for backend data in store? is ok if i do it in getter in a store class?

thanks.

components/MessageList.js

class MessageList extends Component {

  constructor(props) {
    super(props)
    this.renderMessage = this.renderMessage.bind(this)
    this.state = {

      loaded: false,
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      })
    }
  }

  componentDidMount() {
    messageActions.getAll()
    messageStore.addChangeListener(this._onChange)
  }


  _onChange() {
    console.log('on change') // <-- not being called from this point
    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(messageStore.getAll())
    })
  }

  //...
}  

stores/MessageStore.js

let _messages = {}

function create(text, latitude, longitude) {

  fetch('http://localhost:3000/api/message', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      content: text,
      latitude: latitude,
      longitude: longitude
    })
  })
  .then(r => r.json())
  .then(data => {
    this.props.navigator.pop()
  })
  .done()
}


function getAllMessages(callback) {
  fetch('http://localhost:3000/api/message')
    .then((res) => res.json())
    .then((data) => {

      callback(data)

    })
    .done()
}

class MessageStore extends EventEmitter {

  constructor() {
    super()

  }

  emitChange() {
    this.emit('change')
  }

  addChangeListener(callback) {
    console.log('here') // <-- works
    // this.on('change', callback) // <-- not working
    this.on('change', () => console.log('helloooo')) // <-- not working
  }

  getAll() {
    return _messages
  }

}

dispatcher.register(action => {

  switch(action.actionType) {

    case 'MESSAGE_CREAT':
      text = action.text.trim();
      if (text !== '') {
        create(text, action.latitude, action.longitude)
        messageStore.emitChange()
      }
      break
    case 'MESSAGE_ALL':
      console.log('store..');
      getAllMessages(data => _messages = data)
      messageStore.emitChange()

  }

})


const messageStore = new MessageStore()
export default messageStore
shangsunset
  • 1,585
  • 4
  • 22
  • 38

1 Answers1

0

You cannot call the change listener in the store, you are only setting it up there. Try adding:

addChangeListener(callback) {
    this.on('change', callback);
}

Instead of:

addChangeListener(callback) {
   console.log('here') // <-- works
   // this.on('change', callback) // <-- not working
   this.on('change', () => console.log('helloooo')) // <-- not working
}

When a change happens, the changeListener in the store will trigger the change listener in MessageList:

messageStore.addChangeListener(this._onChange)

Then the _onChange function will be called.

Nader Dabit
  • 52,483
  • 13
  • 107
  • 91