我正在尝试使用React和Flux制作预测应用。我从Yahoo Weather API获取数据,并使用jsonp请求中的回调将数据放入我的商店。然后在View中,我从商店获取数据(在componentDidMount()
中)作为状态并传递一些属性它是儿童组件。
作为对象的数据(this.state.store
)有两个属性,名为condition
和forecast
。问题是如果我想传递this.state.store.condition
(或forecast
)给孩子,TypeError: Cannot read property 'condition' of undefined
。但是,如果我只是尝试访问this.state.store
(例如,console.log(this.state.store)
),则没有错误。
另外,如果我尝试在try-catch
语句中访问this.state.store.condition,并在有错误时记录错误,我会在控制台打印TypeError
的情况下成功访问该条件上面提到的。
这是我的代码:
存储
const CHANGE_EVENT = 'change';
let _app = {};
// create a city
function create(city, data) {
_app[city.toUpperCase()] = {
condition: data.condition,
forecast: data.forecast,
};
}
const AppStore = Object.assign({}, EventEmitter.prototype, {
getAll() {
return _app;
},
emitChange() {
this.emit(CHANGE_EVENT);
},
addChangeListener(callback) {
this.on(CHANGE_EVENT, callback);
},
removeChangeListener(callback) {
this.removeListener(CHANGE_EVENT, callback);
},
});
// register callback
AppDispatcher.register((action) => {
switch (action.actionType) {
case AppConstants.CREATE_CITY: {
create(action.city, action.data);
AppStore.emitChange();
break;
}
// other cases
default:
// noop
}
});
动作:
function callback(city, data) {
console.log(data);
const action = {
actionType: AppConstants.CREATE_CITY,
city,
data,
};
AppDispatcher.dispatch(action);
}
const AppActions = {
create(city) {
getDataFromAPI(city, callback);
},
};
utils的:
function getDataFromAPI(query, callback) {
let data;
const url = `https://query.yahooapis.com/v1/public/yql?q=select * from weather.forecast where u='c' AND woeid in (select woeid from geo.places(1) where text="${query}")&format=json`;
superagent
.get(url)
.use(jsonp)
.end((err, res) => {
console.log(res.body.query.results.channel.item);
data = res.body.query.results.channel.item;
callback(query, data);
});
}
的观点:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
store: Store.getAll(),
currentCity: 'BEIJING',
};
this.onChange = this.onChange.bind(this);
this.getCurrentCity = this.getCurrentCity.bind(this);
}
componentWillMount() {
AppActions.create('BEIJING');
}
componentDidMount() {
Store.addChangeListener(this.onChange);
}
onChange() {
this.setState({ store: Store.getAll() });
}
getCurrentCity(city) {
this.setState({ currentCity: city.toUpperCase() });
}
componentWillUnmout() {
Store.removeChangeListener(this.onChange);
}
render() {
// For now, I have to do all of these to pass the condition to the child component
let condition;
let forecast;
let text;
let temp;
let currentWeatherCode;
let forecastWeatherCode = [];
let currentWeatherClassName;
let forecastWeatherClassName = [];
let date;
let forecastDate = [];
console.log(this.state.store[this.state.currentCity]);<--NO ERROR
// console.log(this.state.store[this.state.currentCity])<--UNDEFINED
// console.log(this.state.store[this.state.currentCity].condition);<--CANNOT READ PROPERTY
^
|
ERROR ON THIS 2 STATEMENTS
try {
condition = this.state.store[this.state.currentCity].condition;
forecast = this.state.store[this.state.currentCity].forecast;
text = condition.text.toUpperCase();
temp = condition.temp;
currentWeatherCode = condition.code;
currentWeatherClassName = setWeatherIcon(currentWeatherCode);
date = condition.date;
for (let i = 0; i < 6; i++) {
forecastWeatherCode.push(forecast[i].code);
forecastWeatherClassName.push(setWeatherIcon(forecastWeatherCode[i]));
forecastDate.push(forecast[i].date);
}
} catch (err) {
console.log(err);<--STILL ERROR, BUT I DO ACCESS THE PROP CONDITION IN THIS WAY
}
return (
<div>
<Today
city={this.state.currentCity}
weatherStatus={text}
tempreture={temp}
currentWeatherClassName={currentWeatherClassName}
date={date}
/>
</div>
);
}
}
ReactDOM.render(<App />, document.querySelector('#app'));
答案 0 :(得分:0)
在我看来,您试图在从远程API获取this.state.store[this.state.currentCity]
属性之前尝试访问该属性。
您可以添加某种迹象表明数据仍然是这样提取的。
render() {
// For now, I have to do all of these to pass the condition to the child component
let condition;
let forecast;
let text;
let temp;
let currentWeatherCode;
let forecastWeatherCode = [];
let currentWeatherClassName;
let forecastWeatherClassName = [];
let date;
let forecastDate = [];
console.log(this.state.store[this.state.currentCity]);<--NO ERROR
if (!this.state.store.hasOwnProperty(this.state.currentCity)) {
return <div>Loading...</div>;
}
... the rest of your original code
}
完成加载后,将调用setState()方法并再次调用render()。第二次它将通过if并运行你的代码。