Reputation: 35
in the child component, whenever I click one of the mapped Span elements, the onClick triggers the switchLaunch function in the parent component and triggers the debugger I have there now for testing purposes. However, all the states I had set are now undefined. So when I call this.state.allPastLaunches, it's now undefined but if I call this.allPastLaunches, the data is there. I'm confused as to where I'm going wrong
Parent Component (App)
class App extends Component {
//api call for latest space launch
constructor(props) {
super(props);
this.state = {
selectedLaunch: "",
launchData: "",
videoURL: null,
allPastLaunches: [],
showVideo: false
};
}
componentWillMount() {
this.getLaunchData()
}
switchLaunch(launch) {
debugger
// ALL MY STATES ARE EMPTY HERE WHEN I TRY TO LOG THEM AFTER THE FUNCTION
IS TRIGGERED BY THE CHILD'S ONCLICK
}
getLaunchData() {
// getting latest launch
fetch('https://api.spalta.launch/launch')
.then(response => {
return response.json();
})
.then(json => {
this.setState({
launchData: json,
videoURL: json.links["video_link"],
missionPatch: json.links["mission_patch"]
});
});
//getting all previous launches
fetch('https://api.spalta.launch/prevLaunches')
.then(response => {
return response.json();
})
.then(json => {
this.setState({
allPastLaunches: json,
});
});
}
render() {
let dataReady = this.state.videoURL;
if (this.state.launchData != null) {
return (
<div className="App">
{this.state.allPastLaunches ?
<Header
key="header"
missionPatch = {this.state.missionPatch}
allPastLaunches = {this.state.allPastLaunches}
switchLaunch = {this.switchLaunch}
/>
:
<div>Loading...</div>
}
Child Component (Header)
class Header extends Component {
componentDidMount() {
}
render() {
var launches = this.props.allPastLaunches;
var imgClass = classNames({
'img-container': true,
'animated': true,
'fadeInDownBig': true
});
const component = this;
return (
<div key = "container" className="header-container">
<div key = "img-container">
{launches.map((launch, index) =>
<span key = {index} onClick= {() => { component.props.switchLaunch(index) }} >
{launch["rocket"].rocket_id}
</span>
)}
Upvotes: 3
Views: 2077
Reputation: 11287
You need to bind your method so it has the correct context, you can read more about it here: https://www.andreasreiterer.at/web-development/bind-callback-function-react/
class App extends Component {
//api call for latest space launch
constructor(props) {
super(props);
// This line makes sure that "this" is the correct
// thing when this method is called via callback
this.switchLaunch = this.switchLaunch.bind(this);
this.state = {
selectedLaunch: "",
launchData: "",
videoURL: null,
allPastLaunches: [],
showVideo: false
};
}
componentWillMount() {
this.getLaunchData()
}
switchLaunch(launch) {
debugger
// ALL MY STATES ARE EMPTY HERE WHEN I TRY TO LOG THEM AFTER THE FUNCTION
IS TRIGGERED BY THE CHILD'S ONCLICK
}
...
Old Answer:
Try this:
const component = this
return (
<div key = "container" className="header-container">
<div key = "img-container">
{launches.map((launch, index) =>
<span key = {index} onClick= {() => { component.props.switchLaunch(index) }} >
{launch["rocket"].rocket_id}
</span>
)}
The code (launch, index) =>
creates a new function, so this
is the context of the new function (i.e. the original this
is hidden). You need to save this
as component
and use it in the inner function.
Upvotes: 3