首页 > 解决方案 > 使用中间件处理承诺后无法识别获取的 API 数据

问题描述

如果单击按钮,我一直在构建一个 React-Redux 应用程序来显示一些天气数据(openweathermap.org API)。不知何故,当容器被渲染时,数据没有到达,即使我设法使用 Axios 处理了承诺。
正如您在 console.log 中看到的,“tempo”对象在到达容器后为空。然后,一旦单击按钮,请求就会正确到达容器,并且“tempo”会获取我想要呈现的数据。
当我尝试访问在触发 onClick() 事件之后到达的那些属性时,就会出现问题。它们还不存在,因此整个组件都会引发错误。我认为 Axios 请求中管理的异步等待响应存在一些问题,但我找不到它。抱歉,如果解释不正确,技术性。
我仍然愿意澄清。

带有 API 请求的 Action Creator

import axios from 'axios';

export const GET_CECCIOLA = 'GET_CECCIOLA';


export function submitWeather() {
    const url = 'https://api.openweathermap.org/data/2.5/weather?appid=ce6111c5cb481755173214d6bf62f51a&q=Cecciola,it';
    const cecciola = axios.get(url);

        return {
            type: 'GET_CECCIOLA',
            payload: cecciola
        }
    }

单击按钮时负责渲染的容器

import React, { Component } from 'react';
import {connect} from 'react-redux';

class CecciolaTime extends Component {
    render() {
        console.log(this.props.tempo)


        return (

            <div>
               <h2>{this.props.tempo}                
               </h2>
            </div>
        );
    }

}


function mapStateToProps ({ tempo }) {
    return { tempo };
}

export default connect(mapStateToProps)(CecciolaTime);

带有 onClick() 方法的容器

import React, {Component} from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import {submitWeather } from '../actions/index';



class SearchBar extends Component {
    constructor(props) {
        super(props)


    this.getWeather = this.getWeather.bind(this);

    }


    getWeather(e) {
        e.preventDefault();

        this.props.submitWeather(e);
    }





    render() {
        return (
            <form>
                <button onClick={this.getWeather}>
                tempo a Cecciola
                </button>
            </form>
        )
    }
} 




function mapDispatchToProps(dispatch) {
    return bindActionCreators({ submitWeather }, dispatch);

}

export default connect(null, mapDispatchToProps)(SearchBar);

减速器

import { GET_CECCIOLA } from '../actions/index';


export default function(state = [], action) {
    switch (action.type) {    
    case GET_CECCIOLA:
        return [action.payload.data, ...state];    
    }
    return state;
}

Reducer_Index

import { combineReducers } from 'redux';
import CecciolaReducer from './cecciola_reducer';

export default combineReducers({
    tempo: CecciolaReducer
  })

Store(我使用 Redux-Promise 作为中间件)

import React from 'react';
import './index.css';
import App from './components/App';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import rootReducer from './reducers'
import ReduxPromise from 'redux-promise';

const storeWithMiddleware = applyMiddleware(ReduxPromise)(createStore);

render(
    <Provider store={storeWithMiddleware(rootReducer)}>
      <App />
    </Provider>,
    document.getElementById('root')
  )

标签: javascriptajaxreactjsapiredux

解决方案


如果您试图在tempo对象中显示不存在的属性并且它失败了 - 处理它的最常见方法 - 只需检查此属性是否存在,如下所示:

import React, { Component } from 'react';
import {connect} from 'react-redux';

class CecciolaTime extends Component {

    render() {
        const { name } = this.props.tempo

        return (
            <div>
               {/* Check if name exists then display */}
               <h2>{name && name}</h2>
            </div>
        );
    }

}


function mapStateToProps ({ tempo }) {
    return { tempo };
}

export default connect(mapStateToProps)(CecciolaTime);

注意:您正在尝试{ this.props.tempo }h2标记中渲染对象,这可能会导致另一个错误。

更新(来自评论):我找到了问题,这是因为您将结果设置为数组,它实际上保存在数组中的 0 索引中。因此,您可以通过this.props.tempo[0].name. 为了避免这种混乱,只需使用对象而不是数组作为初始状态,这样处理起来就容易多了。

我用工作代码为你创建了沙箱(点击查看)

希望它会有所帮助。


推荐阅读