Search code examples
reactjsfluxaxios

Trouble populating state via axios


I am trying to use a homespun json API (json-server --watch db.json) to populate the state of a flux store. I am calling a function of the store from a parent component's componentWillMount to load the data with Axios.

I have been looking at the following tutorials for reference: http://mediatemple.net/blog/tips/loading-and-using-external-data-in-react/ https://www.toptal.com/react/tips-and-practices and others.

Here is the JSON data I am pulling in:

[
  {
    "complete": "false",
    "edit": "false",
    "id": "uuid()",
    "text": "Go Shopping"
  },
  {
    "complete": "false",
    "edit": "false",
    "id": "uuid()",
    "text": "Pay Water Bill"
  }
]

db.json gist https://gist.github.com/WebRuin/548f6073ca533016503d34c36116b8de

Here is an excerpt of the Flux store I am calling:

import { EventEmitter } from 'events'
import dispatcher from '../dispatcher'
import axios from 'axios'

import uuid from 'uuid4'

class TodoStore extends EventEmitter {
  constructor() {
    super()
    this.state = {
      todos: [],
      showCompletedTodos: true,
      showIncompletedTodos: true
    }

    this.deleteTodo = this.deleteTodo.bind(this)
    this.toggleTodo = this.toggleTodo.bind(this)
    this.toggleShowCompletedTodos = this.toggleShowCompletedTodos.bind(this)
    this.toggleShowIncompletedTodos = this.toggleShowIncompletedTodos.bind(this)
  }
...

fetchUserState() {
    let th = this
    console.log(th)
    this.serverRequest = 
      axios.get('http://localhost:3000/todos')
        .then(function(result) {
          console.log(result.data)
          th.state.todos = result.data
        })
  }

}

const todoStore = new TodoStore
dispatcher.register(todoStore.handleActions.bind(todoStore))

export default todoStore

Gist of the full file: https://gist.github.com/WebRuin/efbbf4296c566f6eb58cc6d641bee4ba

Console logging gives shows me that the axios request is fulfilled with the data I want and a log of this shows that this.state.todos is being populated, but the react plugin of Chrome does not show the data and hence the app does not display the data.

What am I doing wrong?


Solution

  • Andy is right, except the constructor, we should always use setState() that works asynchronously when setting the state.


    From here: 1 and 2


    However, this is true for the common React. In Flux we should forget the setState method and just work with the stores. This is the message from the article.

    I created one image for my Flux navigation, it may help you.

    enter image description here


    Typically you should load the data via axios, not via the componentWillMount(), but you may use Flux actions flow for that. But still, you can use componentWillMount() to create the action.