javascript - 使用中间件处理承诺后无法识别获取的 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')
)
解决方案
如果您试图在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
. 为了避免这种混乱,只需使用对象而不是数组作为初始状态,这样处理起来就容易多了。
我用工作代码为你创建了沙箱(点击查看)。
希望它会有所帮助。
推荐阅读
- dialogflow-es - Google Actions Builder 和 Google Assistant - 寻找 @sys.any 等效意图
- qt - 如何在 Qt 的记事本中打开扩展名为“.txt”以外的文件
- reactjs - 动态路由变得未定义
- variables - 在 SAS 中将变量重新排序为特定顺序
- ruby-on-rails - 未能为 Rails 项目设置凭证以使用具有 IAM 角色的 S3
- javascript - 缓存后如何清除浏览器中的缓存?
- php - 由于scandir而无法打开文件
- flutter - 如何在颤动中为无线电组设置默认值
- reactjs - 将 useRef 钩子与 React-Admin 一起使用
- apache-kafka - 使用全局商店中的主题在处理器 API 中进行动态路由