我在子组件中调用axios delete方法,并希望刷新父组件以做出反应。当delete((调用时,它从数据库中删除了行,但需要手动重新加载。如果不手动重新加载,我怎么能做到这一点?
我想删除方法作品,同时更新ProductList.js。
import React, { Component } from "react";
import axios from "axios";
import Table from "./Table";
class ProductList extends Component {
constructor(props) {
super(props);
this.state = { productData: [] };
}
componentDidMount() {
axios
.get("http://localhost:8080/products")
.then((response) => {
console.log("responseProductList==", response);
this.setState({ productData: response.data });
})
.catch(function (error) {
console.log(error);
});
}
tabRow() {
return this.state.productData.map(function (object, i) {
return <Table obj={object} key={i} />;
});
}
render() {
return (
<div style={{ paddingTop: "25px" }}>
<h4 align="center">Product List</h4>
<table className="table table-striped" style={{ marginTop: 10 }}>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Price</th>
<th colSpan="4">Action</th>
</tr>
</thead>
<tbody>{this.tabRow()}</tbody>
</table>
</div>
);
}
}
export default ProductList;
import React, { Component } from "react";
import axios from "axios";
import { Link, withRouter } from "react-router-dom";
// import ProductList from "./ProductList";
// import AddProduct from "./AddProduct";
class Table extends Component {
// constructor(props) {
// super(props);
// }
deleteProduct = () => {
console.log("delete button clicked");
axios
.delete("http://localhost:8080/products/" + this.props.obj.id)
.then((res) => {
if (res.status === 200) {
alert("getStatusInDelete");
// return axios.get("http://localhost:8080/products/");
// this.forceUpdate(<ProductList />);
this.props.history.push("/ProductList");
} else {
console.log("Not refresh");
}
})
.catch((err) => console.log(err));
};
render() {
return (
<tr>
<td>{this.props.obj.id}</td>
<td>{this.props.obj.name}</td>
<td>{this.props.obj.price}</td>
<td>
<Link
to={"/EditProduct/" + this.props.obj.id}
className="btn btn-success"
>
Edit
</Link>
</td>
<td>
<button
type="button"
onClick={this.deleteProduct}
className="btn btn-danger"
>
Delete
</button>
</td>
</tr>
);
}
}
export default withRouter(Table);
首先,您不应该使用索引作为密钥,而应该使用产品的id,因为如果您使用索引,在删除后可能会遇到奇怪的错误。为了更新列表,我会传递一个回调onDelete(id(并在父级中处理它。像这样:
import React, { Component } from "react";
import axios from "axios";
import Table from "./Table";
class ProductList extends Component {
constructor(props) {
super(props);
this.state = { productData: [] };
}
componentDidMount() {
axios
.get("http://localhost:8080/products")
.then((response) => {
console.log("responseProductList==", response);
this.setState({ productData: response.data });
})
.catch(function (error) {
console.log(error);
});
}
//****** This is the callback you are going to pass ********
onProductDeleted = (id) => {
this.setState((state) => ({ productData: state.productData.filter(x => x.id !== id) })
}
tabRow() {
return this.state.productData.map(object => {
//********* Passing the callback ************
return <Table obj={object} key={object.id} onDeleted={this.onProductDeleted} />;
});
}
render() {
return (
<div style={{ paddingTop: "25px" }}>
<h4 align="center">Product List</h4>
<table className="table table-striped" style={{ marginTop: 10 }}>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Price</th>
<th colSpan="4">Action</th>
</tr>
</thead>
<tbody>{this.tabRow()}</tbody>
</table>
</div>
);
}
}
export default ProductList;
import React, { Component } from "react";
import axios from "axios";
import { Link, withRouter } from "react-router-dom";
class Table extends Component {
deleteProduct = () => {
console.log("delete button clicked");
axios
.delete("http://localhost:8080/products/" + this.props.obj.id)
.then((res) => {
if (res.status === 200) {
alert("getStatusInDelete");
this.props.history.push("/ProductList");
//****** Invoke the callback after successfully deleted *****
this.props.onDeleted(this.props.obj.id);
} else {
console.log("Not refresh");
}
})
.catch((err) => console.log(err));
};
render() {
return (
<tr>
<td>{this.props.obj.id}</td>
<td>{this.props.obj.name}</td>
<td>{this.props.obj.price}</td>
<td>
<Link
to={"/EditProduct/" + this.props.obj.id}
className="btn btn-success"
>
Edit
</Link>
</td>
<td>
<button
type="button"
onClick={this.deleteProduct}
className="btn btn-danger"
>
Delete
</button>
</td>
</tr>
);
}
}
export default withRouter(Table);
以下是一些可以帮助您了解React:的来源
-
状态更新可能是异步的:https://reactjs.org/docs/state-and-lifecycle.html#state-更新可能是异步
-
以下是使用索引作为键可能是个坏主意的原因:https://medium.com/@vraa/wy-使用-an-index-as-key-in-react-is-probably--bad-idea-7543de68b17c
当产品成功删除时,您需要更新父状态。
这样做的方法是在父组件中定义更新逻辑,然后在删除成功时从子组件调用该函数。
// Define your update product logic here
// It will get productId (or any other unique key) as parameter
// and will use that unique key to update the producsts
// I've added an example logic but yours can be different
updateProducts = (productId) => {
let productsClone = { ...this.state.productData };
const productIndex = productsClone.findIndex(item => item.id == productId);
if (productIndex > -1) {
productsClone.splice(productIndex, 1);
this.setState({ productData: productsClone });
}
}
tabRow() {
return this.state.productData.map(function (object, i) {
// pass your `this.updateProducts` as a props to your child component
return <Table obj={object} key={i} updateProducts={this.updateProducts} />;
});
}
deleteProduct = () => {
axios
.delete("http://localhost:8080/products/" + this.props.obj.id)
.then((res) => {
if (res.status === 200) {
// Finally, here, call the updateProucts when API return success and make sure to pass the correct key as a parameter
this.props.updateProducts(res.data.id);
} else {
console.log("Not refresh");
}
})
.catch((err) => console.log(err));
};
最终答案:它经过了轻微的编辑,现在运行良好。
import React, { Component } from "react";
import axios from "axios";
import Table from "./Table";
class ProductList extends Component {
constructor(props) {
super(props);
this.state = { productData: [] };
}
componentDidMount() {
axios
.get("http://localhost:8080/products")
.then((response) => {
console.log("responseProductList==", response);
this.setState({ productData: response.data });
})
.catch(function (error) {
console.log(error);
});
}
//****** This is the callback you are going to pass ********
onProductDeleted = (id) => {
this.setState((state) => ({ productData: state.productData.filter(x => x.id !== id) })
)}
tabRow = () => {
return this.state.productData.map(object => {
//********* Passing the callback ************
return <Table obj={object} key={object.id} onDeleted={this.onProductDeleted} />;
});
}
render() {
return (
<div style={{ paddingTop: "25px" }}>
<h4 align="center">Product List</h4>
<table className="table table-striped" style={{ marginTop: 10 }}>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Price</th>
<th colSpan="4">Action</th>
</tr>
</thead>
<tbody>{this.tabRow()}</tbody>
</table>
</div>
);
}
}
export default ProductList;
import React, { Component } from "react";
import axios from "axios";
import { Link, withRouter } from "react-router-dom";
class Table extends Component {
deleteProduct = () => {
console.log("delete button clicked");
axios
.delete("http://localhost:8080/products/" + this.props.obj.id)
.then((res) => {
if (res.status === 200) {
alert("getStatusInDelete");
// this.props.history.push("/ProductList");
//****** Invoke the callback after successfully deleted *****
this.props.onDeleted(this.props.obj.id);
} else {
console.log("Not refresh");
}
})
.catch((err) => console.log(err));
};
render() {
return (
<tr>
<td>{this.props.obj.id}</td>
<td>{this.props.obj.name}</td>
<td>{this.props.obj.price}</td>
<td>
<Link
to={"/EditProduct/" + this.props.obj.id}
className="btn btn-success"
>
Edit
</Link>
</td>
<td>
<button
type="button"
onClick={this.deleteProduct}
className="btn btn-danger"
>
Delete
</button>
</td>
</tr>
);
}
}
export default withRouter(Table);