【问题标题】:Redux: Call to action-creator returns 'Cannot read property 'props' of undefined'Redux:调用action-creator返回'无法读取未定义的属性'props'
【发布时间】:2017-12-30 09:15:54
【问题描述】:

我能够获取给定城市的天气,但不知道如何在之后将其删除。 作为 Redux 的新手,我试图弄清楚我在这个谜题中遗漏了哪些部分。

我将 FETCH_WEATHER 代码留给上下文建议。我的问题在于 DELETE_CITY 实现。

错误:

步骤:

  • 在每一行中添加一个调用动作创建者的按钮。

  • 动作创建者采用“城市”的名称并返回“DELETE_CITY”类型的动作。

  • Reducer,监视该类型并遍历城市数组并删除具有给定城市名称的对象。

动作创建者

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
    }
}

减速器:index.js

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

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

export default rootReducer;

weather_reducer.js

DELETE_CITY 的案例是否正确实施?

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;
}
  • 在每一行中添加一个按钮来调用动作创建者。

Ps:mapStateToProps 和 mapDispatchToProps 是否正确?

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);

我需要将动作创建者绑定到 onClick 事件。 我尝试了两种方法:胖箭头函数和/或“将方法绑定在构造函数()中”。

它们都返回未定义的道具。

【问题讨论】:

    标签: javascript reactjs redux react-redux


    【解决方案1】:

    您收到的错误消息 cannot read property props of undefined 表示在 this.props this 中未定义。

    这是反应中的一个常见问题,主要是因为它脱离了上下文。

    你需要做的是在构造函数中将renderWeather函数绑定到WeatherList

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

    另一种选择是使用箭头函数

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

    您也可以在删除城市时在您的 reducer 中考虑此实现。

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

    .filter() 返回一个新的满足给定条件的项数组

    【讨论】:

    • 对于您的派送问题,请尝试bindActionCreators({ deleteCity, weather }, dispatch)
    【解决方案2】:

    你需要绑定renderWeather函数。

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

    【讨论】:

      【解决方案3】:

      尝试替换:

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

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

      map 的第二个参数是thisArg - 执行callback 时用作this 的值。

      【讨论】:

      • 感谢 CD,之前的错误消失了。现在,当我触发 click 事件时,它会出错:调度不是函数。它在抱怨我的 mapDispatchToProps()。
      • 试试function mapDispatchToProps(dispatch) { return bindActionCreators({deleteCity}, dispatch) }
      • CD,请检查我的案例 DELETE_CITY:在我的 weather_reducer 中?删除操作有效!但是,它正在删除整个对象,而不是在数组内一次删除/删除一个城市。非常感谢。
      猜你喜欢
      • 2021-01-15
      • 2018-07-13
      • 1970-01-01
      • 2018-06-14
      • 2020-01-08
      • 2020-10-10
      • 2019-02-15
      • 2021-05-23
      • 1970-01-01
      相关资源
      最近更新 更多