Sathya
Sathya

Reputation: 1734

How to create API calls in React FLUX?

I'm new to flux. I'm struggling past 10 hrs to resolve this issues. I have created one sample todo app. Initially i want to load some data from server. But i don't know how to get that data. While i'm clicking the button that time i'm able to get the data. Please someone help me out from this problem. Because i'm trying to finish this one from long time.

My sample code,

App.js

var React  = require('react');
import * as TodoActions from "./js/Actions";
import TodoStore from "./js/stores/EventLists";

export class EventListing extends React.Component {
  constructor() {
    super();
    this.getTodos = this.getTodos.bind(this);
    this.state = {
      todos: TodoStore.getAll(),
    };
  }

  componentWillMount() {
    TodoStore.on("change", this.getTodos);
  }

  componentWillUnmount() {
    TodoStore.removeListener("change", this.getTodos);
  }

  getTodos() {
    this.setState({
      todos: TodoStore.getAll(),
    });
  }

  reloadTodos() {
    TodoActions.reloadTodos();
  }

  render() {
    var List = this.state.todos.map(function(el, i){
      return <li key={i}>
        <div>{el.STA_NAME}</div>
      </li>;
    });
    return (
      <div className="listing">
        <button onClick={this.reloadTodos.bind(this)}>Reload!</button>
        <ul>
          {List}
        </ul>
      </div>
    );
  }
}

var Events = React.createClass({
    render:function(){
        return (<div>
               <EventListing />
        </div>);
    }
});

module.exports = Events;

Store.js

import EventEmitter from 'events';
import dispatcher from "../dispatcher"

class EventLists extends EventEmitter {
  constructor(){
      super();
      this.todos = [{}];
  }
  createTodo(text) {
    const id = Date.now();

    this.todos.push({
      id,
      text,
      complete: false,
    });

    this.emit("change");
  }
    getAll() {
    return this.todos;
    }
  handleActions(action) {
    switch(action.type) {
      case "CREATE_TODO": {
        this.createTodo(action.text);
        break;
      }
      case "RECEIVE_TODOS": {
        this.todos = action.todos;
        this.emit("change");
        break;
      }
    }
  }
};

const eventLists = new EventLists;
dispatcher.register(eventLists.handleActions.bind(eventLists));
export default eventLists;

Action.js

import dispatcher from "./dispatcher";

export function createTodo(text) {
  dispatcher.dispatch({
    type: "CREATE_TODO",
    text,
  });
}

export function deleteTodo(id) {
  dispatcher.dispatch({
    type: "DELETE_TODO",
    id,
  });
}

export function reloadTodos() {
    var loadData;
    $.ajax({
        url:url,
        type:'GET',
        contentType: 'application/json; charset=UTF-8',
        dataType:'json',
        success:function(data) {
            loadData = data;
        }.bind(this)
    });
    dispatcher.dispatch({type: "FETCH_TODOS"});
    setTimeout(() => {
        console.log(loadData);
        dispatcher.dispatch({type: "RECEIVE_TODOS", todos: loadData});
    }, 1000);
}

Dispatcher.js

import { Dispatcher } from "flux";

export default new Dispatcher;

Upvotes: 2

Views: 1458

Answers (2)

pachonjcl
pachonjcl

Reputation: 741

I've tried your code and the only thing that you need to change is on Action.js.

Because of the ajax call, you have to wait until the response comeback and user the dispatcher before ajar call with event FETCH_TODOS and on success function with event RECEIVE_TODOS.

Timeout is a bad idea to wait an ajax response.

export function reloadTodos() {
    dispatcher.dispatch({type: "FETCH_TODOS"});
    var loadData;
    $.ajax({
        url:url,
        type:'GET',
        contentType: 'application/json; charset=UTF-8',
        dataType:'json',
        success:function(data) {
            loadData = data;
            dispatcher.dispatch({type: "RECEIVE_TODOS", todos: loadData});
        }
    });
}

EDITTED

Ok now I understand a little more

please add this method to Action.js

export function loadData() {
    dispatcher.dispatch({ type: "FETCH_TODOS" });
    $.ajax({
        url: "https://jsonplaceholder.typicode.com/todos/",
        type: 'GET',
        contentType: 'application/json; charset=UTF-8',
        dataType: 'json',
        success: function(response) {
            dispatcher.dispatch({ type: "RECEIVE_TODOS", todos: response });
        }
    });
}

and call it on your app.js on the constructor method so you can have the data initialized at the very begining

export class EventListing extends React.Component {
  constructor() {
    super();
    this.getTodos = this.getTodos.bind(this);
    this.state = {
      todos: TodoStore.getAll(),
    };
    TodoActions.loadData();
  }

Note that because of flux you will get the data correctly when RECEIVE_TODOS be handled

Upvotes: 2

Sean Armstrong
Sean Armstrong

Reputation: 43

If you want to load the data on initial load you should add a componentDidMount which calls the reloadTodos action.

componentDidMount() {
  TodoActions.reloadTodos();
}

Make sure to call this side effect in DidMount and not WillMount so the new store state will correctly trigger a re-render showing your data (it should be pretty instant)

Finally, as @pachon_1992 said you should not be using a timeout to wait for your ajax response instead you should dispatch on success

Upvotes: 0

Related Questions