Redux:调用 action-creator 返回“无法读取未定义的属性‘props’”

IT技术 javascript reactjs redux react-redux
2021-04-29 16:24:25

我能够获取给定城市的天气,但无法弄清楚之后如何删除它。作为 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 是否正确?

天气容器.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 事件。我尝试了两种方法:粗箭头函数和/或“在构造函数()中绑定方法”。

他们都返回未定义的props。

3个回答

尝试更换:

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

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

的第二个参数map执行时thisArg使用- 值thiscallback

你需要绑定renderWeather函数。

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

您收到的错误消息cannot read property props of undefined意味着 inthis.props this未定义。

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

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

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

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

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

删除城市时,您也可以在减速器中考虑此实现。

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

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