首页 文章

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

提问于
浏览
0

这是我第一次体验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发送到有效负载时,它会返回错误 - 未定义响应 . 我究竟做错了什么?

附:我还尝试创建const result = []而不是result = [... response.data] . 错误是 - SyntaxError:“result”是只读的

4 回答

  • 1

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

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

  • 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
          });
        });
    
      }
    }
    
  • 1

    您的代码的问题是,当您返回时,响应仍未定义,因为此代码同步运行直到return语句 . 正如你所看到的,响应是在_1020561中定义的 . 所以这就是你需要做的真正的魔法 return ,但另一种方式 .

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

    //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)
    

    正如你从@loelsonk的回答中看到的那样 . 如果您使用 redux-thunk ,那么您将无需为调用者 redux-thunk 传递调度 . 但是还要注意你将如何返回以及接受调度作为参数的匿名箭头函数 .

  • 1

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

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

    $action_type_PENDING 在我们的行动发送后立即 $action_type_FULFILLED 如果api呼叫成功, $action_type_REJECTED 如果api呼叫失败

    见文档 - https://github.com/pburtchaell/redux-promise-middleware

    我项目的例子 -

    你的行动是

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

    减速机是

    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;
        }
    };
    

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

    const isLoading = (state = initialState.isLoading, action) => {
        switch(action.type) {
            case (action.type.match(/_PENDING/) || {}).input:
                return true;
    
            case (action.type.match(/_FULFILLED/) || {}).input:
                return false;
    
            default: return state;
        }
    };
    

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

相关问题