React,Redux和Axios - 尝试进行API调用

时间:2017-07-05 10:45:04

标签: reactjs redux axios

这是我第一次体验React,Redux和我完全迷失了。问题是我的行动:

import axios from 'axios';
import { FETCH_MOVIE } from '../constants/actionTypes';
const API_KEY = <API_KEY>;
const ROOT_URL = `<API_URL>`;


export function fetchMovies(pop){

  const url = `${ROOT_URL}?api_key=${API_KEY}&sort_by=${pop}`;
  axios.get(url)
  .then(function (response) {
    console.log("response is",response)
  })
  .catch(function (error) {
    console.log(error);
  });

  return{
    type:  FETCH_MOVIE,
    payload: response.data
  };
}

Screenshot of Console.log

在Console.log上看起来很好 - 我可以看到响应有我需要的数据。但是当我尝试将response.data发送到有效负载时,它会返回错误 - 未定义响应。我究竟做错了什么?

P.S。我还尝试创建const result = []而不是result = [... response.data]。错误是 - SyntaxError:&#34;结果&#34;是只读的

4 个答案:

答案 0 :(得分:1)

const错误是因为,结果是一个在执行过程中发生变化的变量,你必须使用'let'而不是'const'。

现在,对于修复,未定义响应来自最后一次返回。一个好的方法是,不应该在这个函数fetchMovies上返回动作,而是应该调度一个新的动作,例如dispatch(fetchMoviesSuccess(payload))而不是“console.log(”response is“,response)”,这将是调度将触发减速器的动作,然后更新应用程序的状态。

答案 1 :(得分:1)

您的代码的问题是,当您返回时,响应仍未定义,因为此代码同步运行直到return语句。  如您所见,响应在<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://maps.googleapis.com/maps/api/js"></script> <div id="map-canvas"></div>中定义  所以这就是你需要用你的实际魔法console.log("response is",response)但另一种方式。

你可以使用redux-thunk来做这些事情,因为这是redux async。但是我觉得你是我见过的代码的初学者,只需使用更简单的方法并阅读returnredux-thunk。如果你认为你的项目需要这个,那就去吧。

redux-promise

正如你从@loelsonk的回答中看到的那样。如果您使用//try to make the caller pass this.props.dispatch as param export function fetchMovies(dispatch, pop){ const url = `${ROOT_URL}?api_key=${API_KEY}&sort_by=${pop}`; axios.get(url) .then(function (response) { // only here is response define so use dispatch to triger another action (fetched data with response) dispatch({ type: FETCH_MOVIE, payload: response.data }) }) .catch(function (error) { //if you had a loader state, you call also toggle that here with erro status console.log(error); }); } //now on the caller (onClick for instance) do this instead fetchMovies(this.props.dispatch, pop) ,则无需为调用者redux-thunk传递调度。但是还要注意你将如何返回以及接受调度作为参数的匿名箭头函数。

答案 2 :(得分:1)

您正在使用axios执行async请求。您应该使用redux-thunk发送您的操作。安装很简单,请阅读有关thunk here的更多信息。

然后你的行动应该是这样的:

export function fetchMovies(pop) {
  return dispatch => {
    const url = `${ROOT_URL}?api_key=${API_KEY}&sort_by=${pop}`;
    axios.get(url)
    .then(function (response) {
      console.log("response is",response);

      dispatch({
        type:  FETCH_MOVIE,
        payload: response.data
      });

    })
    .catch(function (error) {
      console.log(error);
      // You can dispatch here error 
      // Example
      dispatch({
        type:  FETCH_MOVIE_FAILED,
        payload: error
      });
    });

  }
}

答案 3 :(得分:1)

您可以使用redux promise中间件。我在我的新项目中使用了这个。它非常简单,可以使我们的代码和状态易于管理。

对于每个异步操作调度,它都会调度

我们的行动发送后立即<{$action_type_PENDING {1}}如果api呼叫成功,$action_type_FULFILLED如果api呼叫失败

请参阅文档 - https://github.com/pburtchaell/redux-promise-middleware

我的项目示例 -

你的行动是

$action_type_REJECTED

reducer是

export function getQuestions() {
    return {
        type: types.GET_QUESTIONS,
        payload: axios.get('http://localhost:3001/questions')
    };
}

为了在api调用时显示加载器,我们可以使用以下reducer

const initialState = {
    isLoading: false,
    questions: []
};

const questions = (state = initialState.questions, action) => {
    switch(action.type) {
        case types.GET_QUESTIONS_FULFILLED:
            return [...action.payload.data];

        default: return state;
    }
};

如果您需要有关上述内容的更多详细信息,请评论我。