im a beginner, im trying to make a memory game this component fetches data for an api then trims it down with only that has image link
then on level one it should display 3 random image from fetch data it always displayedChars: [undefined, undefined, undefined]
constructor(props) {
super()
this.state = {
level: 1,
numImg: 1*3,
displayedChars: [],
chars: []
}
}
async componentDidMount() {
await this.loadData().then(data => {
this.setState({
chars: this.trimData(data)
});
});
await this.displayChars().then(data => {
console.log(data)
this.setState({
displayedChars: data
});
});
console.log(this.state);
}
async loadData() {
try {
const res = await fetch(`http://hp-api.herokuapp.com/api/characters`)
const characters = await res.json();
return characters
} catch(err) {
console.error(err)
}
}
trimData(characters) {
const listChars = []
characters.map(char => {
if(char.image !== "") {
listChars.push(char)
}
})
return listChars
}
displayChars() {
return (new Promise((resolve) => {
const list = []
for(let x=1; x<= this.state.numImg; x++) {
let randomNum = Math.floor(Math.random() * 24);
list.push(this.state.chars[randomNum]);
}
console.log(list)
resolve(list)
}))
}
in the this.displayChars() console.log(data) works fine but
this.setState({
displayedChars: data
});
then console.log(this.state) OUTPUT: [undefined, undefined, undefined]
setState is async, so you cannot see the updated states immediately, that's why your console.log is [undefined, undefined, undefined]. You can assign variables to handle responses separately instead of using this.state.
The second concern is you shouldn't mix then and async/await. I'd prefer using async/await alone in your case.
async componentDidMount() {
const chars = await this.loadData();
const displayedChars = await this.displayChars();
this.setState({
displayedChars: displayedChars
chars: this.trimData(chars)
});
//states are not updated right away
//console.log(this.state);
//access via variable
console.log({ chars, displayedChars })
}