Just to mention, I did not find an answers for my particular situation on similar post.
My app allows a user to get a city's weather along with a relevant packing list for that weather.
I want to make each city's card deletable and have an 'X' placed that should call an updateTerms action creator, which would in turn remove it from the users list and update the dom.
The callback seems to fire, but this.props.updateTerms throws **TypeError: Cannot read property 'props' of null at handleDeleteCard **
a_result_card.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import ATodoList from './a_Todo_List';
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
import { bindActionCreators} from 'redux';
import { updateTerms } from '../actions';
class AResultCard extends Component {
constructor(props) {
super(props);
this.state = { cityName : '' };
this.handleDeleteCard = this.handleDeleteCard.bind(this);
}
handleDeleteCard(event) { // I NEED TO CALL THIS WITH THE KEY
//So THAT I CAN REMOVE IT FROM THE USERS TERM LIST
event.preventDefault();
debugger;
this.props.updateTerms(cityName, "delete");
}
renderWeather(cityData) {
function calcAverageTemp(days) {
let reduced = days.reduce((sum,day) => {
return sum + day.main.temp_max;
}, 0);
return Math.floor(reduced / cityData.list.length);
};
function calcAverageHumidity(days) {
let reduced = days.reduce((sum,day) => {
return sum + day.main.humidity;
}, 0);
return Math.floor(reduced / cityData.list.length);
};
const avgTempK = calcAverageTemp(cityData.list);
const cityName = cityData.city.name;
const avgTempF = Math.floor((avgTempK * 1.8) - 459.67 );
const avgHumidity = calcAverageHumidity(cityData.list);
return (
<li key={cityName} className="result-card">
<div className="card">
<div className="">
<div className="weather-details">
<div className="card-heading">
<span className="weather-detail detail-title">{cityName}</span>
<span className="weather-detail">{avgTempF} °F</span>
<span className="weather-detail">H: {avgHumidity}%</span>
<span className="weather-detail delete-card-icon" onClick={handleDeleteCard}>X</span>
</div>
</div>
<ATodoList avgTempF={avgTempF} />
</div>
</div>
</li>
);
}
render() {
return (
<ul className="results">
<CSSTransitionGroup
transitionName="example"
transitionEnterTimeout={150}
transitionLeaveTimeout={150}>
{this.props.weather.map(this.renderWeather)}
</CSSTransitionGroup>
</ul>
);
}
}
function mapStateToProps({weather, userTerms}) {
return ({
weather,
userTerms
});
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({ updateTerms }, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(AResultCard);
You need to call your handleDeleteCard
function like
<span className="weather-detail delete-card-icon" onClick={this.handleDeleteCard}>X</span>
since it belongs to the context of the React Component
and not the renderWeather
function
Also bind the renderWeather function
renderWeather = (cityData) => {
function calcAverageTemp(days) {
let reduced = days.reduce((sum,day) => {
return sum + day.main.temp_max;
}, 0);
return Math.floor(reduced / cityData.list.length);
};
function calcAverageHumidity(days) {
let reduced = days.reduce((sum,day) => {
return sum + day.main.humidity;
}, 0);
return Math.floor(reduced / cityData.list.length);
};
const avgTempK = calcAverageTemp(cityData.list);
const cityName = cityData.city.name;
const avgTempF = Math.floor((avgTempK * 1.8) - 459.67 );
const avgHumidity = calcAverageHumidity(cityData.list);
return (
<li key={cityName} className="result-card">
<div className="card">
<div className="">
<div className="weather-details">
<div className="card-heading">
<span className="weather-detail detail-title">{cityName}</span>
<span className="weather-detail">{avgTempF} °F</span>
<span className="weather-detail">H: {avgHumidity}%</span>
<span className="weather-detail delete-card-icon" onClick={this.handleDeleteCard}>X</span>
</div>
</div>
<ATodoList avgTempF={avgTempF} />
</div>
</div>
</li>
);
}