Reputation:
I am creating a simple Todo App, I am using componentDidMount to display the data from the database. But the problem is, Once I add a new data the data gets stored but it doesn't display on to the page unless I refresh it.
Then I came across componentDidUpdate. It works perfectly, But it re-renders multiple times, What I mean is it keeps requesting the server to check for new data. I am using Express for backend
So could anyone tell me how to prevent this ? or if there is any better solution?
Here is the current code:
class Navbar extends Component {
state = {
userArray: [],
username: "",
email: ""
};
//Storing the Data
addBtn = e => {
e.preventDefault();
var data = {
username: this.state.username,
email: this.state.email
};
fetch("/user", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
})
.then(response => {
if (response.status >= 400) {
throw new Error("Bad response from server");
}
return response.json();
})
.then(data => {
console.log(data);
if (data === "success") {
console.log("Yay");
}
})
.catch(err => {
console.log(err);
});
console.log(this.state.userArray);
};
componentDidMount() {
this.displayData();
}
componentWillUpdate() {
this.displayData();
}
//Displaying the Data
displayData() {
fetch("/user")
.then(data => data.json())
.then(data => {
this.setState({
userArray: data
});
});
}
//Handling the input values
logChange = e => {
this.setState({
[e.target.name]: e.target.value
});
};
Upvotes: 0
Views: 747
Reputation: 3323
Everyone gave the right answer , But there is a tiny mistake.
You should call the displayData()
outside of the if condition
.then(data => {
console.log(data);
if (data === "success") {
console.log("Yay");
}
this.displayData();
})
Upvotes: 0
Reputation: 3487
So, let's try and understand why there was a lot of calls to the server.
When componentDidMount
is created, you called displayData
, which then setState. As soon as setstate is called, it calls componentDidUpdate
which calls displayData
again, which then calls setState. And the loop goes on (probably till you run out of memory).
You could try this class:
import React from 'react';
export default class Navbar extends React.Component {
state = {
userArray: [],
username: '',
email: ''
};
componentDidMount() {
this.displayData();
}
addBtn = e => {
e.preventDefault();
var data = {
username: this.state.username,
email: this.state.email
};
fetch('/user', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(response => {
if (response.status >= 400) {
throw new Error('Bad response from server');
}
return response.json();
})
.then(data => {
console.log(data);
if (data === 'success') {
this.displayData();
}
})
.catch(err => {
console.log(err);
});
};
displayData() {
fetch('/user')
.then(data => data.json())
.then(data => {
this.setState({
userArray: data
});
});
}
}
Basically, what I did was I removed the call to displayData in componentDidUpdate and then called the displayData when the ApI call was successful
Upvotes: 1
Reputation: 3117
componentDidMount
is the right place to load the first time, and then, after creating new Todo, you need to refresh the list right after POST request complete
.then(data => {
console.log(data);
if (data === "success") {
console.log("Yay");
this.displayData();
}
})
To impove performace, you should return new Todo record after POST
, so you only push it to the list userArray
in state, no need to fetch whole list again
Upvotes: 1
Reputation: 4330
For this, you need to first understand how componentDidMount and componentWillUpdate works in React. They are lifecycle methods of react.
componentDidMount gets called after the component is mounted. It gets called only once and never gets called again if not unmounted and mounted again.
componentWillUpdate gets called every time state changes and re-rendering is going to happen.
As commented by @trixn: You need to call this.setState() in addBtn when you have the data instead of repeatedly calling this.displayData()
Upvotes: 0