При доступе к состоянию Redux через this.props выдается «Не удается прочитать имя свойства undefined». - PullRequest
0 голосов
/ 25 октября 2018

Представление Redux Dev Tools Редактировать: Вот изображение из избыточных devtools.Это заполнение состояния массивом объектов.Каждый раз, когда я пытаюсь получить доступ к объекту в массиве, я получаю эту ошибку React Error

У меня есть сервер, который получает данные от yelp, когда он получает запрос на получение и отправляет ответ отвскрикнуть до клиента.

Когда я пытаюсь получить доступ к ответу сервера, который был вызван из функции getFoodPlans (), он отображается как состояние в избыточных веб-инструментах, но говорит: «Не удается найти имя свойства undefined», если вы пытаетесь получить к нему доступчерез реквизит.

Если я использую вызов axios для конечной точки и устанавливаю локальное состояние с ответом, я могу получить доступ ко всем свойствам.У меня такое ощущение, что это связано с сервером, потому что, если я отправляю весь бизнес-объект с сервера, я получаю ту же ошибку с axios, когда не могу получить доступ к свойству undefined.

Это связано с тем, как я отправляю данные с сервера клиенту?

Спасибо.

Сервер:

 router.get('/food', (req, res) => {
  const position = Math.floor(Math.random() * 15);
  axios
   .get(`${foodSearch}location=kansascity
         &&radius=${radius}&&cost=1,2,3&&categories=food`, {
         headers: { Authorization: `Bearer ${apiKey}` }
    })
    .then(result => {
      res.json(result.data.businesses[position]);
    })
    .catch(err => console.log(err));
});

PlanActions.js:

import axios from 'axios';
import { GET_FOOD_PLANS, PLAN_LOADING, GET_ERRORS, GET_ACTIVITY_PLANS } from 
'./types';

// Get Plans
export const getFoodPlans = () => dispatch => {
  dispatch(setPlanLoading());
  axios
    .get('/api/data/food')
    .then(res =>
      dispatch({
        type: GET_FOOD_PLANS,
        payload: res.data
      })
    )
    .catch(err =>
      dispatch({
        type: GET_FOOD_PLANS,
        payload: err
      })
    );
};

planReducer.js:

import { GET_FOOD_PLANS, GET_ACTIVITY_PLANS, PLAN_LOADING } from 
'../actions/types';

const initalState = {
  food: {},
  activities: {},
  triggered: false,
  loading: false
};

export default function(state = initalState, action) {
  switch (action.type) {
    case PLAN_LOADING:
      return {
        ...state,
        loading: true
      };
    case GET_FOOD_PLANS:
      return {
        ...state,
        food: action.payload,
        loading: false
      };
    case GET_ACTIVITY_PLANS:
      return {
        ...state,
        activities: action.payload,
        loading: false
      };
    default:
      return state;
  }
}

PlanTestival.js:

import React from 'react';
import PropTypes from 'prop-types';
import { getFoodPlans } from '../../actions/planActions';
import { connect } from 'react-redux';
import axios from 'axios';

import ResultBox from '../Resultbox/ResultBox';

class PlanTomorrow extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      load: false,    
      activity1: {},
    };
  }

  componentWillMount() {
    this.props.getFoodPlans();
    axios.get('/api/data/activity').then(res => this.setState({ activity1: 
    res.data }));
  }

  render() {
    return (
      <div className="tomorrowform">
        <h2>Tomorrows Plan:</h2>
        <ul className="tomorrowform-data">
          <li id="item1">
            <ResultBox
              activity={this.props.plan.food.name}
              phone={this.props.plan.food.display_phone}
              rating={this.props.plan.food.rating}
            />
          </li>
          <li id="item2">
            <ResultBox
              activity={this.state.activity1.name}
              phone={this.state.activity1.display_phone}
              rating={this.state.activity1.rating}
            />
         </li>
        </ul>
      </div>
    );
  }
}

PlanTomorrow.propTypes = {
  auth: PropTypes.object.isRequired,
  plan: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth,
  plan: state.plan
});

export default connect(
  mapStateToProps,
  { getFoodPlans }
)(PlanTomorrow);

1 Ответ

0 голосов
/ 25 октября 2018

Две точки:

  1. Выполните вызов API из componentDidMount ().Лучше всего для внешних вызовов API.По совету реагирующих документов.
  2. Вы должны называть свое действие как this.props.getFoodPlans(), когда вы передаете его в компонент через соединение.
  3. Поскольку вы выполняете внешний вызов в компоненте, ваши данные не будутбыть в правильной форме на первом рендере.Вы должны проверить это тоже.Добавьте это перед возвратом в вашем методе рендеринга.
const isFoodExists = !this.props.plan.food || !this.props.plan.food.length;

if (this.props.loading || !isFoodExists) {
  return null;
}

Здесь вы должны вернуть данные для еды в виде массива.И передайте его как массив вашим компонентам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...