Reputation: 43
I am trying to create a simple table using ReactJS to display user information. Here's how the general code structure looks like:
class ParentComponent extends React.Component {
state = {
data : []
}
componentDidMount() {
// initializes state with data from db
axios.get("link/").then(res => {
this.setState({data: res.data});
});
// I should be able to call this.getData() instead
// of rewriting the axios.get() function but if I do so,
// my data will not show up
}
// retrieves array of data from db
getData = () => {
axios.get("link/").then(res => {
this.setState({data: res.data});
});
}
render() {
return (
<div>
<ChildComponent data={this.state.data} refetch={this.getData} />
</div>
)
}
}
Each of the generated rows should have a delete function, where I'll delete the entry from the database based on a given id. After the deletion, I want to retrieve the latest data from the parent component to be redisplayed again.
class ChildComponent extends React.Component {
// deletes the specified entry from database
deleteData = (id) => {
axios.get("deleteLink/" + id).then(res => {
console.log(res);
// calls function from parent component to
// re-fetch the latest data from db
this.props.refetch();
}).catch(err => {console.log(err)});
}
render() {
let rows = null;
if(this.props.data.length) {
// map the array into individual rows
rows = this.props.data.map(x => {
return (
<tr>
<td>{x.id}</td>
<td>{x.name}</td>
<td>
<button onClick={() => {
this.deleteData(x.id)
}}>
Delete
</button>
</td>
</tr>
)
})
}
return (
<div>
<table>
<thead></thead>
<tbody>
{rows}
</tbody>
</table>
</div>
)
}
}
The two problems which I encountered here are:
So far I have tried:
this.forceUpdate()
- doesn't workthis.setState({})
- empty setState doesn't work eithercomponentDidMount()
to componentDidUpdate()
- error showing that I have "reached maximum depth" or something along that lineAny help is appreciated. Thanks in advance.
EDIT: I did some debugging and tracked down the issue, which is not relevant to my question. My deleteData()
which is located in ChildComponent uses axios.post()
instead of axios.get()
, which I overlooked.
deleteData = (id) => {
axios.post("deleteLink/", id).then(res => {
console.log(res);
// calls function from parent component to
// re-fetch the latest data from db
this.props.refetch();
}).catch(err => {console.log(err)});
}
In order for axios.post()
to return a response, in order to perform .then()
, you'll need to add a res.json()
to the routing codes.
Upvotes: 4
Views: 511
Reputation: 1419
I can't find an issue in your code, the only way I can help is to tell you how I would debug it.
edit parent like so:
class ParentComponent extends React.Component {
state = {
data : []
}
componentDidMount() {
// You are right when you say this should works, so
// stick to it until the bug is fixed
console.log("parent mounted");
this.getData();
}
// retrieves array of data from db
getData = () => {
console.log("fetching data");
axios.get("link/").then(res => {
console.log("fetched data", res.data);
this.setState({data: res.data});
});
}
render() {
return (
<div>
<ChildComponent
data={this.state.data}
refetch={this.getData}
/>
</div>
)
}
}
and in the child component add these 2 lifecycle methods just for debugging purposes:
componentDidMount () {
console.log("child mounted", this.props.data)
}
componentDidUpdate (prevProps) {
console.log("old data", prevProps.data);
console.log("new data", this.props.data);
console.log("data are equal", prevProps.data === this.props.data);
}
if you can share the logs I can try help you more
Upvotes: 1
Reputation: 4578
You should map data into your child.
Change your parent like this:
class ParentComponent extends React.Component {
state = {
data : []
}
componentDidMount() {
this.getData();
}
getData = () => axios.get("link/").then(res => this.setState({data: res.data});
deleteData = (id) => axios.get("deleteLink/" + id).then(res => this.getData())
.catch(err => { console.log(err) });
render() {
return (
<div>
<table>
<thead></thead>
<tbody>
{this.state.data.map(x => <ChildComponent row={x} deleteData={this.deleteData} />)}
</tbody>
</table>
</div>
)
}
}
And your child component should be like this
const ChildComponent = ({row,deleteData}) => (
<tr>
<td>{row.id}</td>
<td>{row.name}</td>
<td><button onClick={() => deleteData(row.id)}>Delete</button></td>
</tr >
)
Upvotes: 3