W
W
waweca2015-08-27 16:06:44
JavaScript
waweca, 2015-08-27 16:06:44

How to make a correct ajax request in React Redux?

In general, I'm trying to understand the Flux approach in React in RoR. Advised to learn Redux.
Installed gem 'react-rails'.
Redux installed via npm
package.json - it looks something like this.

{
  "version": "0.1.1",
  "main": "index.js",
  "dependencies": {
    "react": "^0.13.3",
    "react-redux": "^1.0.1",
    "redux": "^1.0.1",
    "redux-thunk": "^0.1.0"
  },
  "devDependencies": {
    "babelify": "^6.2.0",
    "browserify": "^11.0.1",
    "browserify-incremental": "^3.0.1"
  }
}

So, I'm trying to get ajax from the server. I realized that it should be done in action. But how?
Now the action looks like this.
export const LOAD_INFO = 'LOAD_INFO';

export function loadInfo() {
  return {
    type: 'LOAD_INFO',
    info: // ?
  }
}

Before in the component, I did it like this.
componentDidMount: function() {
  $.ajax({
    url: this.props.url,
    dataType: 'json',
    type: 'GET',
    success: function(data, textStatus, jqXHR) {
      this.setState({
        book: data.book,
        magazine: data.magazine
      });
    }.bind(this),
    error: function(xhr, status, err) {
      console.error(this.props.url, status, err.toString());
    }.bind(this)
  });
}

UPD:
In action I receive data from the server.
import request from 'axios';

export const LOAD_INFO = 'LOAD_INFO';

export function loadInfo() {
  return {
    type: 'LOAD_INFO',
    info: request.get(Routes.root_path(), {
      headers: {
        'Accept': 'application/json'
      }
    })
  }
}

reducer
import { LOAD_INFO }
from '../actions/action';

export default function info(state = 0, action) {
  switch (action.type) {

    case LOAD_INFO:
      return action;

    default:
      return state;
  }
}

component
import React, { Component, PropTypes } from 'react';

class Info extends Component {
  render() {
    const { info } = this.props;
    return (
      <div>
        { info }
      </div>
    );
  }
}

Info.propTypes = {
  info: PropTypes.object.isRequired
};

export default Info;

Answer the question

In order to leave comments, you need to log in

4 answer(s)
V
vsuhachev, 2015-08-27
@waweca

Because ajax requests are asynchronous, then for each such request 3 branches of the development of events are made:
In code it will look something like this

export function loadInfo() {
    return dispatch => {

        dispatch({
            type: 'LOAD_INFO_REQUESTED'
        });

        request.get(
            Routes.root_path(),
            {headers: {'Accept': 'application/json'}}
        )
            .then(result => {
                dispatch({
                    type: 'LOAD_INFO_OK',
                    info: result.data
                })
            })
            .catch(result => {
                dispatch({
                    type: 'LOAD_INFO_FAIL',
                    errors: result.statusText
                })
            })
    }
}

Those. first, the action notifies the store that it has started a request and makes the request itself. Further, depending on the result, the repository will be notified either on success or failure.
To access dispatch inside the action, redux-thunk is used, which you have already installed.
Next, the reducer, 3 types of events from the action are processed
const defaultState = { loading: false, info: null, errors: null };

export default function info(state = defaultState, action) {
  switch (action.type) {

    case LOAD_INFO_REQUESTED:
      return { loading: true };

    case LOAD_INFO_OK:
      return { loading: false, info: action.info, errors: null };

    case LOAD_INFO_FAIL:
      return { loading: false, info: null, errors: action.errors };

    default:
      return state;
  }
}

The component must be connected to the store using connect, without it the component will not see the store
@connect(state => ({
    info: state.info
}))

class Info extends Component {

    componentDidMount() {
        const { dispatch } = this.props;
        dispatch(loadInfo()) // Вызываем загрузку
    }

  render() {
    const { loading, info, errors } = this.props.info;

    if (loadind) { return (<div>Loading</div>) }
    if (errors != null) { return (<div>Error!</div>) }
    return (
      <div>
        { info }
      </div>
    );
  }
}

In general, something like that. In the help on redux, this is all described.

M
Maxim, 2016-02-16
@maxfarseer

I made a similar tutorial, where asynchronous requests are also understood. I will be glad if I help - https://www.gitbook.com/book/maxfarseer/redux-cour...

S
Shane Matte, 2017-02-07
@mattedev

There is an excellent module, axios. Returns promises. Very comfortably

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question