Получение "Uncaught TypeError: Невозможно прочитать свойство 'results' of undefined" при отображении данных из API с использованием Redux - PullRequest
0 голосов
/ 04 марта 2020

Я пытаюсь отобразить данные из API movieDB в React & Redux и получаю сообщение об ошибке:

Uncaught TypeError: Cannot read property 'results' of undefined

Для лучшего понимания вот мой код.

редукторы / видеоредукторы. js

const initialState = {
  isFetchingMovies: false,
  isFetchedMovies: false,
  movieList: [],
  fetchingMoviesError: null
}

export const popularMoviesReducer = (state = initialState, action) => {
  switch (action.type) {
    case "FETCHING_POPULAR_MOVIES_START":
      return { ...state, isFetchingMovies: true, fetchingMoviesError: null }
    case "FETCHING_POPULAR_MOVIES_SUCCESS":
      return {
        ...state,
        isFetchingMovies: false,
        isFetchedMovies: true,
        movieList: action.data,
        fetchingMoviesError: null
      }
    case "FETCHING_POPULAR_MOVIES_FAILURE":
      return { ...state, fetchingMoviesError: action.data.error }
    default:
        return state
  }
}

редукторы / указатели. js

import { combineReducers } from "redux"
import { popularMoviesReducer } from "./moviesReducer"

const rootReducer = combineReducers({
  popularMoviesReducer
})

export default rootReducer

действия / индекс. js

export const fetchPopularMovies = () => {
  return async dispatch => {
    dispatch({ type: "FETCHING_POPULAR_MOVIES_START" })
    try {
      const res = await axios.get(url)
      dispatch({
        type: "FETCHING_POPULAR_MOVIES_SUCCESS",
        data: { popularMovies: res.data }
      })
    } catch (err) {
      dispatch({
        type: "FETCHING_POPULAR_MOVIES_FAILURE",
        error: { error: "Something went wrong" }
      })
    }
  }
}

Компоненты / Популярные. js

import React, { Component } from "react"
import { connect } from "react-redux"
import { fetchPopularMovies } from "../actions/index"

class Popular extends Component {

  componentDidMount() {
    this.props.dispatch(fetchPopularMovies())
  }

  render() {
    const { isFetchingMovies, movieList } = this.props

    return isFetchingMovies ? (
      <p>Loading...</p>
    ) 

    :

    (

      <div>
        {
          movieList && movieList.popularMovies.results.map(movie => {
            <p>{movie.title}</p>
          })
        }
      </div>
    )
  }
}

const mapStateToProps = state => {
  return {
    isFetchingMovies: state.popularMoviesReducer.isFetchingMovies,
    movieList: state.popularMoviesReducer.movieList
  }
}

export default connect(mapStateToProps)(Popular)

Я всегда застреваю в такой проблеме всякий раз, когда мне нужно отобразить некоторые данные в моем компоненте. Мне нужно, наконец, узнать, как избавиться от этого!

Обновление : Вот скриншот того, что там в Popular. js в React-Dev- Инструменты. Скриншот

1 Ответ

0 голосов
/ 04 марта 2020

Измените способ извлечения фильмов:

используйте функцию наподобие mapDispatchToProps для отправки действий от вашего компонента:

const mapDispatchToProps = dispatch => ({
 fetch: () => dispatch(youractions.fetchPopularMovies())
})

и в ловушке жизненного цикла вашего компонента:

componentDidMount() {
    this.props.fetch();
  }

вызов подключения теперь должен выглядеть следующим образом:

export default connect(mapStateToProps, mapDispatchToProps)(Popular)

ОБНОВЛЕНИЕ:

Вы также должны вернуть тег внутри функции карты и также должны используйте ключевую опору (должна быть уникальной).

  <div>
   {
      movieList && movieList.popularMovies.results.map(movie => {
        return <p key={movie.title}>{movie.title}</p>
      })
    }
  </div>

Если заголовок уникален, если у вас есть идентификаторы, вы также можете использовать их.

ОБНОВЛЕНИЕ № 2:

Логическая ошибка в вашем редукторе изначально isFetchingMovies в вашем initialState должно быть true, а не false, потому что если это false, вы попытаетесь отобразить фильмы до того, как они будут выбраны.

Поэтому измените initialState на следующее:

const initialState = {
  isFetchingMovies: true,
  isFetchedMovies: false,
  movieList: [],
  fetchingMoviesError: null
}

Обратите внимание, что метод рендеринга вызывается до componentDidMount. У вас также, кажется, есть isFetchedMovies, который изменяется при получении фильмов, вы можете использовать это состояние в вашем mapStateToProps и использовать его в качестве проверки для отображения загрузки или фильмов.

...