Redux + Thunk + Axios + Потребление внешнего API: Uncaught TypeError: Не удается прочитать свойство «1» неопределенного

Я только начинаю с Redux и внешних API. Для обучения я хотел использовать API от НАСА (https://api.nasa.gov/). Я не знаю, что я делаю неправильно. Я не могу ничего отображать на экране. Я получаю «Uncaught TypeError: Невозможно прочитать свойство« 1 »неопределенного» в консоли.

Я прочитал несколько вопросов и ответов в stackoverflow... Но я не понял, в чем проблема в моем коде.

Буду очень признателен за любое мнение. Мне нужна подсказка... Заранее спасибо.

введите здесь описание изображения

КОНТЕЙНЕР

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;

person Dubliner    schedule 29.04.2017    source источник


Ответы (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
  }
}
person Shota    schedule 29.04.2017
comment
Спасибо за ваш быстрый ответ @Shota. Я включил ваше предложение. Теперь ошибка не появляется, но на экране ничего не отображается. Любая подсказка? Кстати, у меня уже есть в моем контейнере. - person Dubliner; 29.04.2017
comment
Не могли бы вы console.log что содержит this.props.tutusers? - person Shota; 29.04.2017
comment
Привет @Шота. Если консоль лог Сначала пустой массив, позже: Object {photos: Array(856)}Если кликну: photos : Array(856) Если кликну: [0 … 99] Если кликну, то вы увидите данные объектов. В основном то, что вы можете видеть на моем предыдущем скриншоте. - person Dubliner; 29.04.2017
comment
Если я веду консольный журнал this.props.tutusers.photos, сначала я получаю undefined, а через несколько секунд получаю: [Object, Object, Object...]< /б>. Но если я веду консольный журнал this.props.tutusers.photos[1], я получаю Uncaught TypeError: Cannot read property '1' of undefined, и через несколько секунд ничего не меняется. . - person Dubliner; 29.04.2017

У меня есть решение в этом вопросе о стеке: не визуализировать 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>
      )
    })
 }
person Dubliner    schedule 30.04.2017