Redux + Thunk + Axios + Consume external API: "Uncaught TypeError: Невозможно прочитать свойство" 1 "из неопределенного"
Я только начинаю с Redux и внешних API. Для обучения я хотел использовать API от НАСА ( https://api.nasa.gov/). Я не знаю, что я делаю неправильно. Я не могу ничего сделать на экране. Я получаю "Uncaught TypeError: Невозможно прочитать свойство" 1 "из неопределенного" в консоли.
Я прочитал несколько вопросов и ответов в stackru... Но я не выяснил, где проблема в моем коде.
Буду очень признателен за любое мнение. Мне нужна подсказка... Заранее спасибо.
КОНТЕЙНЕР
import React from 'react';
import { Component } from 'react';
import { connect } from 'react-redux'
import { showTutusers } from '../actions/index';
import { bindActionCreators } from "redux";
class TutuserListContainer extends Component {
componentWillMount() {
this.props.showTutusers()
}
render() {
return (
<div>
<h3> { this.props.tutusers.photos[0].id}</h3><br />
<h3> { this.props.tutusers.photos[1].id}</h3><br />
</div>
);
}
}
function mapStateToProps(state) {
return {
tutusers: state.tutuser.tutusers
}
}
export default connect(mapStateToProps, { showTutusers })(TutuserListContainer)
РЕДУКТОРЫ - ИНДЕКС
import {combineReducers} from 'redux';
import { showTutusers } from './tutusers'
const allReducers = combineReducers({
tutuser: showTutusers,
});
export default allReducers
РЕДУКТОР
import { FETCH_TUTUSERS_START, FETCH_TUTUSERS_ERROR, RECEIVED_TUTUSERS } from '../actions/action-types';
const initialState = {
fetching: false,
fetched: false,
tutusers: [],
error: null
}
export function showTutusers(state = initialState, action) {
switch (action.type) {
case FETCH_TUTUSERS_START: {
return {...state, fetching: true}
break;
}
case FETCH_TUTUSERS_ERROR: {
return {...state, fetching: false, error: action.payload}
break;
}
case RECEIVED_TUTUSERS: {
return {...state, fetching: false, fetched: true, tutusers: action.payload}
break;
}
}
return state
}
Остросюжетные ВИДЫ
export const SHOW_TUTUSERS = 'SHOW_TUTUSERS';
export const FETCH_TUTUSERS_START = 'FETCH_TUTUSERS_START';
export const FETCH_TUTUSERS_ERROR = 'FETCH_TUTUSERS_ERROR';
export const RECEIVED_TUTUSERS = ' RECEIVED_TUTUSERS';
ДЕЙСТВИЯ - ИНДЕКС
import * as types from '../actions/action-types';
import axios from 'axios';
import store from '../stores/store';
export function showTutusers() {
return (dispatch, getState) => {
store.dispatch( { type: types.FETCH_TUTUSERS_START} )
axios.get('https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?sol=1000&api_key=_____MY_KEY____')
.then((response) => {
store.dispatch( { type: types.RECEIVED_TUTUSERS, payload: response.data } )
// console.log(">>> response.data", response.data)
})
.catch((err) => {
dispatch({type: "FETCH_TUTUSERS_ERROR", payload: err})
})
}
}
ХРАНИТЬ
import { createStore, applyMiddleware, compose } from 'redux';
import allReducers from '../reducers';
import thunk from 'redux-thunk';
// import promise from 'redux-promise';
import createLogger from 'redux-logger';
import promise from 'redux-promise-middleware';
const middleware = applyMiddleware(thunk, promise(), createLogger());
const store = createStore(
allReducers,
compose(middleware, window.devToolsExtension ? window.devToolsExtension() : f => f)
);
export default store;
2 ответа
Вам нужно подождать, пока ответ не будет получен, и только затем попытаться получить доступ к фотографиям, что-то вроде этого должно помочь:
<div>
{this.props.tutusers.fetched && <div>
<h3> { this.props.tutusers.photos[0].id}</h3><br />
<h3> { this.props.tutusers.photos[1].id}</h3><br />
</div>}
</div>
Вам также необходимо передать все данные о запросе:
function mapStateToProps(state) {
return {
tutusers: state.tutuser
}
}
В этом вопросе stackru я получил решение: реагирующий компонент redux-thunk не отображает this.props
В основном мне нужно было только выражение if else:
render() {
var component;
if (this.props.tutusers) {
component = this.functionToRenderTutusers()
} else {
component = <h3>Loading...</h3>;
}
return (
<div>
{component}
</div>
);
};
functionToRenderTutusers() {
return this.props.tutusers.photos.map((tutuser) => {
return (
<div>{tutuser.id}</div>
)
})
}