2017-07-24 4 views
0

Ich kann das Wetter von einer bestimmten Stadt abrufen, kann aber nicht herausfinden, wie ich es danach löschen kann. Ich bin immer noch neu in Redux und versuche herauszufinden, welche Teile ich in diesem Puzzle vermisse.Redux: Call to action-creator gibt 'Props' von 'undefined' kann nicht gelesen werden

Ich lasse den FETCH_WEATHER Code nur für den Kontext schlägt. Meine Probleme sind mit der DELETE_CITY-Implementierung.

Bug: enter image description here

Schritte:

  • Fügen Sie eine Schaltfläche in jeder Zeile, dass Anrufe ein Action-Schöpfer.

  • Der Ersteller der Aktion nimmt den Namen der 'Stadt' und gibt eine Aktion vom Typ 'DELETE_CITY' zurück.

  • Reduzierung, Uhren für diesen Typ und iteriert durch das Array von Städten und löscht das Objekt mit dem gegebenen Stadtnamen.

Aktion Schöpfer

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

export const FETCH_WEATHER = 'FETCH_WEATHER'; 
export const DELETE_CITY = 'DELETE_CITY'; 

//fetch cities 
export function fetchWeather(city){ 
    const url = `${ROOT_URL}&q=${city},&units=imperial`; 
    const request = axios.get(url); 
    console.log('Request:', request); 

    return { 
     type: FETCH_WEATHER, 
     payload: request 
    } 
} 

//Delete Cities 
export function deleteCity(city) { 
    return { 
     type: DELETE_CITY, 
     payload: city 
    } 
} 

Reducer: index.js

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

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

export default rootReducer; 

weather_reducer.js

Ist der Fall für DELETE_CITY genau implementiert?

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

export default function (state = [], action) { 
    console.log('Action received', action); 

    //only fetch weather data type 
    switch (action.type) { 
     case FETCH_WEATHER: 
      //concat to prevent state mutation 
      return state.concat([action.payload.data]); 

     case DELETE_CITY: 
      return state 
       .slice(0, action.payload.data) 
       .concat([action.payload.data].slice([action.payload.data] + 1)); 
    } 
    return state; 
} 
  • eine Schaltfläche in jeder Zeile hinzufügen, die eine Aktion Schöpfer nennt.

Ps: Sind mapStateToProps und mapDispatchToProps korrekt?

weather_container.js

import React, { Component } from 'react'; 
import { connect } from 'react-redux'; 
import Chart from '../components/chart'; 
import GoogleMap from '../components/google_map'; 
import { bindActionCreators } from 'redux'; 
import { deleteCity } from '../actions/index'; 

class WeatherList extends Component { 

    renderWeather(cityData) { 
     const name = cityData.city.name; 

     return (
      <tr key={name}> 
       <td><button onClick={() => this.props.deleteCity(cityData)} className="btn btn-danger">x</button></td> 
      </tr> 
     ) 
    } 
    render() { 
     return (
      <table> 
       <thead> 
        <tr> 
         <th>City</th> 
        </tr> 
       </thead> 
       <tbody> 
       {this.props.weather.map(this.renderWeather)} 
       </tbody> 
      </table> 
     ) 
    } 
} 

function mapStateToProps(state) { 
    return { 
     weather: state.weather 
    } 
} 

function mapDispatchToProps(dispatch, weather) { 
    return bindActionCreators({deleteCity},{weather}, dispatch) 
} 

export default connect(mapStateToProps, mapDispatchToProps)(WeatherList); 

Ich brauche die Aktion Schöpfer an das OnClick-Ereignis zu binden. Ich habe beide Methoden ausprobiert: fette Pfeilfunktionen und/oder 'die Methode innerhalb eines Konstruktors binden()'.

Beide kehren mit Requisiten undefined zurück.

Antwort

3

Try replaceing:

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

Mit

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

Das zweite Argument ist der mapthisArg - Wert als this zu verwenden, wenn callback ausführt.

+0

Dank CD zu erfüllen, wird vorheriger Fehler verschwunden. Jetzt wenn ich das Click-Event fire it: Versand ist keine Funktion. Es beschwert sich über meine mapDispatchToProps(). – tonkihonks13

+0

Try 'Funktion mapDispatchToProps (Versand) { return bindActionCreators ({} deleteCity, Versand) }' –

+0

CD, cld Sie bitte meinem Fall DELETE_CITY überprüfen: in meinem weather_reducer? Die Löschaktion funktioniert! Es löscht jedoch das gesamte Objekt im Gegensatz zum Löschen/Entfernen von jeweils nur einer Stadt innerhalb des Arrays. Ich danke dir sehr. – tonkihonks13

1

Sie müssen renderWeather Funktion binden.

class WeatherList extends Component { 
    constructor(){ 
     super(); 
     this.renderWeather = this.renderWeather.bind(this); 
    } 
    ... 
} 
1

Die Fehlermeldung Sie cannot read property props of undefined immer bedeutet, dass in this.propsthis nicht definiert ist.

Es ist eine häufige Reaktion, hauptsächlich weil es aus dem Zusammenhang gerät.

Was müssen Sie tun, ist die renderWeather Funktion WeatherList im Konstruktor binden

constructor() { 
    this.renderWeather = this.renderWeather.bind(this) 
} 

Eine weitere Alternative ist Pfeil Funktionen nutzen

class { 
    renderWeather = (weatherData) => { 
     ... 
    } 
    ... 
} 

Sie könnten auch diese Implementierung berücksichtigen in Sie Minderer, wenn eine Stadt löschen

[...state].filter((weather) => { 
    return weather.id != action.payload.data.id 
}) 

.filter() ein neues Array von Elementen zurückgibt, die die gegebene Bedingung

+0

Für Ihr Versandproblem versuchen Sie 'bindActionCreators ({deleteCity, Wetter}, Versand)' –

Verwandte Themen