Reputation: 4623
I'm new to React and have been struggling with this issue for the last 2 days. Why does the call to this.imgList() work when I put it in render (can't be there - performance issues), but doesn't when it's in componentDidMount?
So I set the state within the constructor:
class PersonalBananas extends React.Component {
constructor(){
super();
this.state = {
username: 0,
images: 0,
pred: 0,
IMAGES: 0
}
}
Then in componentDidMount I have two ajax calls which work and the call to imgLis() which doesn't:
componentDidMount() {
axios.get('http://localhost:8081/auth/username')
.then((response) => {
let uname = response.data;
this.setState({
username: uname
});
})
axios.get('http://localhost:8081/auth/files')
.then((response) => {
let imgs = response.data;
console.log("images response: "+imgs);
this.setState({
images: imgs
});
})
this.imgList();
}
This method I call from my imgLis(), there are some ajax calls:
getImgPred = (path) => {
var username = this.state.username;
var $this = this;
let regex = new RegExp(username+'\/(.*?)$');
let imgRegex= /{username}\/(.*?)$/;
let filename = regex.exec(path);
console.log("filename at front:"+filename[1]);
console.log("regex1:"+imgRegex+", regex2:"+regex);
axios.post('http://localhost:8081/auth/imgpred',
"filename=" + filename[1]
).then(function (response) {
console.log("response at front (get img prediction):"+response.data);
if (response.status === 200) {
$this.setState({
pred: response.data
});
}
});
}
Then there is this infamous imgLis(), which works like a charm when I call it directly from render, but now doesn't:
imgList = () => {
var $this = this;
const IMAGES = [];
const imgpaths = this.state.images;
for (let i = 0; i < imgpaths.length; i++) {
var path = imgpaths[i]
this.getImgPred(path);
console.log("pred:"+$this.state.pred);
IMAGES.push({
src: process.env.PUBLIC_URL +`/${path}`,
thumbnail: process.env.PUBLIC_URL +`/${path}`,
thumbnailWidth: 320,
thumbnailHeight: 320,
caption: $this.state.pred
})
}
this.setState({
IMAGES: IMAGES
})
};
And in my render() I try to get the IMAGES -doesn't work, BUT it works when I replace {this.state.IMAGES} with {this.imgLis()} and in imgLis() just return IMAGES...
render() {
return (
<div>
<Gallery images={this.state.IMAGES}/>
</div>
)
}
}
export default PersonalBananas;
Any help?
Upvotes: 1
Views: 189
Reputation: 14413
In componentDidMount
, use a callback function after this.setState
like so:
axios.get('http://localhost:8081/auth/files')
.then((response) => {
let imgs = response.data;
console.log("images response: "+imgs);
this.setState({
images: imgs
}, () => {
this.imgList();
});
})
The reason being that this.imgList()
uses this.state.images
, but this.setState()
is not synchronous in React. Since render()
is called after every this.setState()
your function worked there, because this.state.images
is defined but not in componentDidMount()
Upvotes: 2
Reputation: 429
componentDidMount() run once, but you have async API calls (axios) inside it. When this.imgList() is called in componentDidMount(), most probably you had not get your response back yet.
Simple fix is
axios('http://localhost:8081/auth/files')
.then((response) => {
let imgs = response.data;
console.log("images response: "+imgs);
this.setState(
{images: imgs},
this.imgList // Will run after setState is completed
);
})
Upvotes: 0