Reputation: 135
I fetch a list of files from backend and push it to the array of objects (dirloc) in component state. At the moment console log shows multiple logs of dirloc for each file. I want to setState once everything is pushed to the dirloc. How to do it?
class Load extends Component {
constructor({ props, token }) {
super(props, token);
this.state = {
nodeRes: [],
dirloc: []
};
}
componentDidMount() {
fetch("http://192.168.22.124:3000/loadit/", {
headers: new Headers({
authorization: `Bearer ${this.props.token}`,
"Content-Type": "application/json"
})
})
.then(response => response.json())
.then(logit => {
let { dirloc, nodeRes } = this.state;
logit.map(verifypath => {
let getpath = verifypath.substring(0, verifypath.lastIndexOf("/"));
let dirnames = getpath
.toString()
.split("/")
.pop();
return getpath !== ""
? (dirloc.push({
getpath: getpath /* for e.g '/folder/of/files/' */,
dirnames: dirnames /* array of folder names */,
ffiles: verifypath /* full path '/folder/of/files/abc.jpg' */
}),
this.setState({ dirloc }, () => {
console.log(this.state.dirloc);
}))
: (nodeRes.push(verifypath), this.setState({ nodeRes }));
});
})
.then(getdata => this.allFetch(this.state.nodeRes));
}
}
render() {
const { dirloc } = this.state;
let folderView;
for (var i = 0; i < dirloc.length; i++) {
if (Object.entries(dirloc).length !== 0 && dirloc.constructor !== Object) {
folderView = <Filetree fileloc={this.state.dirloc} token={this.props.token} />
console.log(`dirs: ${dirloc[i].getpath}`)
} else {
folderView = null
}
}
Edit: The problem is that when I render with conditional statement, I see that console log shows object multiple times which means it renders child component multiple times. I want to render it once only with all the required objects.
Upvotes: 0
Views: 90
Reputation: 5422
Generate the required values first and then invoke setState once at the end.
fetch('http://192.168.22.124:3000/loadit/', {
headers: new Headers({
authorization: `Bearer ${this.props.token}`,
'Content-Type': 'application/json',
}),
})
.then((response) => response.json())
.then((logit) => {
const { dirloc, nodeRes } = this.state;
const newDirLoc = [];
const newNodeRes = [];
logit.forEach((verifypath) => {
const getpath = verifypath.substring(0, verifypath.lastIndexOf('/'));
const dirnames = getpath.toString().split('/').pop();
getpath !== ''
? newDirLoc.push({
getpath,
dirnames,
ffiles: verifypath,
})
: newNodeRes.push(verifypath);
});
this.setState({
nodeRes: [...nodeRes, ...newNodeRes],
dirloc: [...dirloc, ...newDirLoc]
})
});
At the render, check for the condition before the loop.
render() {
const { dirloc } = this.state;
let folderView;
if (dirloc.length) {
for (let i = 0; i < dirloc.length; i++) {
folderView = <Filetree fileloc={this.state.dirloc} token={this.props.token} />;
console.log(`dirs: ${dirloc[i].getpath}`);
}
} else {
folderView = null;
}
}
Have replaced Object.entries with a simple length check as dirloc is an array.
Upvotes: 1