Ошибка типа: this.props.weather не определено - PullRequest
0 голосов
/ 03 ноября 2018

Я работаю над приложением, которое поможет мне получить пятидневный прогноз погоды для любого города, используя openweathermap.org. Однако я получаю вышеуказанную ошибку в браузере всякий раз, когда вызываю функцию renderWeather в контейнере WeatherList, как показано в моем фрагменте кода ниже.

Этот файл является index.js, куда я импортировал избыточное обещание

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import ReduxPromise from 'redux-promise';

import App from './components/app';
import reducers from './reducers';

const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <App />
  </Provider>
  , document.querySelector('.container'));

Код для контейнера weather_list ниже

import React, {Component} from 'react';
import {connect} from 'react-redux';

class WeatherList extends Component{

renderWeather(cityData){
  return(
    <tr>
      <td>{cityData.city.name}</td>
    </tr>
  );

}

  render(){
    return(
      <table className="table table-hover">
        <thead>
          <tr>
          <th>City</th>
          <th>Temperature</th>
          <th>Pressure</th>
          <th>Humidity</th>
          </tr>
        </thead>
        <tbody>
        {this.props.weather.map(this.renderWeather)}
        </tbody>
      </table>
    );
  }
}
function mapStateToProps(state){
  return {
    weather: state.weather
  };
}
export default connect(mapStateToProps)(WeatherList);

Код для контейнера search_bar ниже

import React, {Component}from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {fetchWeather} from '../actions/index';

class SearchBar extends Component{
  constructor(props){
    super(props);

    this.state = {term: ''};
    this.onInputChange = this.onInputChange.bind(this);
    this.onFormSubmit = this.onFormSubmit.bind(this);
  }

onInputChange(event){
  console.log(event.target.value);
  this.setState({term: event.target.value});
}

onFormSubmit(event){
  event.preventDefault();
  // we need to go and fetch weather data!
  this.props.fetchWeather(this.state.term);
  this.setState({term: ''});
}

  render(){
    return(
      <form onSubmit={this.onFormSubmit} className="input-group">
        <input
          placeholder="Get a five-day forecast in your favorite cities"
          className="form-control"
          value={this.state.term}
          onChange={this.onInputChange} />
        <span className="input-group-btn">
          <button type="submit" className="btn btn-secondary">Submit</button>
        </span>
      </form>
    );
  }
}
function mapDispatchToProps(dispatch){
  return bindActionCreators({fetchWeather:fetchWeather}, dispatch)
}

export default connect(null, mapDispatchToProps)(SearchBar);

Код для компонента приложения показан ниже

import React, { Component } from 'react';
import SearchBar from '../containers/search_bar.js';
import WeatherList from '../containers/weather_list.js';


export default class App extends Component {
  render() {
    return (
      <div>
        <SearchBar />
        <WeatherList />
      </div>
    );
  }
}

Код для погодного редуктора показан ниже

import {FETCH_WEATHER} from '../actions/index';

export default function(state = [], action){
  switch (action.type) {
    case FETCH_WEATHER:
      //return state.concat([action.payload.data]);
      return ([action.payload.data, ...state])
  }
  return state;
}

Код для index.js в папке редукторов показан ниже

import { combineReducers } from 'redux';
import WeatherReducer from './reducer_weather';

const rootReducer = combineReducers({
  weather: WeatherReducer
});

export default rootReducer;

Код создателя действий в папке действий показан ниже

import axios from 'axios';
const API_KEY = '03d17752ca362bc60ca7df94aac228a6';
const ROOT_URL =`https://api.openweathermap.org/data/2.5/forecast?appid=${API_KEY}`;

export const FETCH_WEATHER = 'FETCH_WEATHER';

export function fetchWeather(city){
  const url = `${ROOT_URL}&q=${city},us`;
  const request = axios.get(url);

  console.log('Request:', request);

  return{
    type: FETCH_WEATHER,
    payload: request
  }
}

Наконец, ниже показано изображение, показывающее ошибку в браузере. введите описание изображения здесь

Любая помощь по поводу ошибки очень ценится

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

Изначально this.props.weather будет неопределенным, поэтому перед выполнением .map необходимо выполнить условную проверку, как двумя способами

this.props.weather && this.props.weather.map

OR

Array.isArray(this.props.weather) && this.props.weather.map

Также при работе с .map необходимо передавать данные о погоде в метод renderWeather, потому что он ожидает данные, но вы не передаете ему данные в .map

Изменение

{this.props.weather.map(this.renderWeather)}

К

 {Array.isArray(this.props.weather) && this.props.weather.map(item => this.renderWeather(item))}

Также установите уникальный ключ для элемента tr здесь

renderWeather(cityData){
  return(
    <tr key={cityData.city && cityData.city.id}> //if you do not have unique id then use index as key
      <td>{cityData.city && cityData.city.name}</td>
    </tr>
  ); 
}

или если ваши данные не содержат уникальный идентификатор, используйте индекс в качестве ключа

 {Array.isArray(this.props.weather) && this.props.weather.map((item, index) => this.renderWeather(item, index))}

Также установите уникальный ключ для элемента tr здесь

renderWeather(cityData, index){
  return(
    <tr key={"city-"+index}> //if you do not have unique id then use index as key
      <td>{cityData.city && cityData.city.name}</td>
    </tr>
  ); 
}
0 голосов
/ 03 ноября 2018

Это потому, что this.props.weather означает undefined, поэтому вызов функции .map() для undefined приведет к ошибке. Вы можете добавить проверку вперед, чтобы она вызывала .map() только когда это массив (когда поступают данные).

Вы можете добавить:

Array.isArray(this.props.weather) && ...

Внесите изменения здесь:

import React, {Component} from 'react';
import {connect} from 'react-redux';

class WeatherList extends Component{

renderWeather(cityData){
  return(
    <tr>
      <td>{cityData.city.name}</td>
    </tr>
  );

}

  render(){
    return(
      <table className="table table-hover">
        <thead>
          <tr>
          <th>City</th>
          <th>Temperature</th>
          <th>Pressure</th>
          <th>Humidity</th>
          </tr>
        </thead>
        <tbody>
        {Array.isArray(this.props.weather) && this.props.weather.map(this.renderWeather)}
        </tbody>
      </table>
    );
  }
}
function mapStateToProps(state){
  return {
    weather: state.weather
  };
}
export default connect(mapStateToProps)(WeatherList);
...