我正在创建一个表格,一旦您单击一行,就会打开一个弹出模式,允许您更新该行的内容。模态的关闭顺序会更新更改的firestore,并激活一个道具功能,该功能将更改更新到上述组件中。
关闭模态不会更新表格(我开始意识到它根本不会导致组件重新渲染......)
成分:
父亲上桌:
import React, { Component } from "react";
import { db } from "../../firebase/firebase";
import InventoryTable from "./Table/InventoryTable";
class InventoryPage extends Component {
constructor(props) {
super(props);
this.state = {
filterGroups: [],
data: [],
originalData: [],
};
this.modalUpdate = this.modalUpdate.bind(this);
this.filterGroupToggle = this.filterGroupToggle.bind(this);
}
modalUpdate(modifiedRow) {
let newData = this.state.data;
let oldRow = newData.filter((row) => {
return row.id === modifiedRow.id;
});
let oldRowIndex = newData.indexOf(...oldRow);
newData.splice(oldRowIndex, 1, modifiedRow);
console.log(newData);
this.setState({
data: newData,
});
}
filterGroupToggle(index) {
// Switch the groupFilter that was clicked to ON/OFF
let newFilterGroups = this.state.filterGroups;
newFilterGroups[index].on = !newFilterGroups[index].on;
this.setState({
filterGroups: newFilterGroups,
});
const included = this.state.filterGroups
.filter((group) => {
return group.on;
})
.map((group) => {
return group.name;
});
if (included.length) {
console.log(included);
let newData = this.state.data;
newData = newData.filter((row) => {
return included.includes(row.group);
});
this.setState({
data: newData,
});
} else {
this.setState({
data: this.state.originalData,
});
}
}
componentDidMount() {
db.collection("inventoryData")
.doc("filtering")
.get()
.then((doc) => {
let newFilterGroups = [];
doc.data().groups.map((group) => {
newFilterGroups.push({
name: group,
on: false,
});
return this.setState({
filterGroups: newFilterGroups,
});
});
});
db.collection("inventory")
.get()
.then((quertSnapshot) => {
let data = [];
quertSnapshot.forEach((doc) => {
data.push({
id: doc.id,
...doc.data(),
});
});
this.setState({
data,
originalData: data,
});
});
}
render() {
console.log("InventoryPage render");
const { filterGroups } = this.state;
return (
<>
<div className="container">
<div className="h1 mb-4 mt-2">Inventory</div>
{filterGroups.length ? (
<div className="row justify-content-around">
{filterGroups.map((group, index) => {
return (
<div
key={index}
className={
"col-2 mx-1 mb-3 toggle-buttons " +
(group.on ? "ON" : null)
}
onClick={() => {
this.filterGroupToggle(index);
}}
>
{group.name}
</div>
);
})}
</div>
) : (
<div className="h4">Loading Filtering Groups...</div>
)}
</div>
{this.state.data.length ? (
<InventoryTable db={this.state.data} modalUpdate={this.modalUpdate} />
) : (
<div className="container h4 mt-3">No items to show...</div>
)}
</>
);
}
}
export default InventoryPage;
表格组件:
import React, { useState, useEffect } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faSortUp, faSortDown } from "@fortawesome/free-solid-svg-icons";
import { useTable, useSortBy, useGlobalFilter } from "react-table";
import ManualEditModal from "./ManualEditModal";
import GlobalFilter from "./GlobalFilter";
const InventoryTable = ({ db, modalUpdate }) => {
const [modalData, setModalData] = useState(null);
const [showModal, setShowModal] = useState(false);
useEffect(() => {
console.log("modal data effect");
if (modalData) {
setShowModal(true);
} else {
setShowModal(false);
}
}, [modalData]);
const handleCloseModal = () => {
console.log("close modal");
// setShowModal(false);
setModalData(null);
};
// i'm supposed to use useMemo here,
// but i couldn't find a way to rerender the table
// upon props change aside from deleting useMemo
const data = React.useMemo(db, []);
const columns = React.useMemo(
() => [
{
Header: "Info",
columns: [
{
Header: "Name",
accessor: "name", // accessor is the "key" in the data
},
{
Header: "Type",
accessor: "type",
},
],
},
{
Header: "Stock",
columns: [
{
Header: "Current Stock",
accessor: "stock",
},
{
Header: "Awaiting Arrival",
accessor: "await_arrival",
},
{
Header: "Awaiting Order",
accessor: "await_order",
},
],
},
],
[]
);
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
state,
setGlobalFilter,
} = useTable({ columns, data }, useGlobalFilter, useSortBy);
const { globalFilter } = state;
return (
<div className="container mt-3">
{showModal ? (
<div className="editRowModal">
<ManualEditModal
show={showModal}
data={modalData}
onHide={handleCloseModal}
modalUpdate={modalUpdate}
/>
</div>
) : null}
<div className="form-group mb-3">
<GlobalFilter filter={globalFilter} setFilter={setGlobalFilter} />
</div>
<table {...getTableProps()} className="table table-bordered">
<thead className="thead-dark">
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th
{...column.getHeaderProps(column.getSortByToggleProps())}
scope="col"
>
{column.render("Header")}
<span className="sorting-icon">
{column.isSorted ? (
column.isSortedDesc ? (
<FontAwesomeIcon icon={faSortUp} className="ml-2" />
) : (
<FontAwesomeIcon icon={faSortDown} className="ml-2" />
)
) : (
""
)}
</span>
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map((row) => {
prepareRow(row);
return (
<tr
{...row.getRowProps()}
onClick={() => {
setModalData(row.original);
}}
>
{row.cells.map((cell) => {
return (
<td {...cell.getCellProps()}>{cell.render("Cell")}</td>
);
})}
</tr>
);
})}
</tbody>
</table>
</div>
);
};
export default InventoryTable;
模态组件:
import React, { useState } from "react";
import { Modal, Button } from "react-bootstrap";
import { db } from "../../../firebase/firebase";
const ManualEditModal = ({ show, data, onHide, modalUpdate }) => {
const [stock, setStock] = useState(data ? data.stock : -1);
// update the database on the new stock value
const onSave = () => {
if (isNaN(Number(stock)) || stock < 0) {
alert("Invalid value");
return;
}
db.collection("inventory")
.doc(data.id)
.update({
stock: Number(stock),
})
.then(() => {
// call a function to update the state (and therefore the table) on the new values.
data.stock = Number(stock);
modalUpdate(data);
onHide();
});
};
if (show && data) {
return (
<Modal show={show} onHide={onSave}>
<Modal.Header closeButton>
<Modal.Title>{data.name}</Modal.Title>
</Modal.Header>
<Modal.Body>
<div className="input-group">
<div className="input-group-prepend">
<span className="input-group-text">Current Stock</span>
</div>
<input
className="form-control"
type="number"
value={stock}
onChange={(e) => {
setStock(e.target.value);
}}
/>
</div>
</Modal.Body>
<Modal.Footer>
<Button variant="primary" onClick={onSave}>
Save & Close
</Button>
<Button variant="secondary" onClick={onHide}>
Close
</Button>
</Modal.Footer>
</Modal>
);
} else {
return null;
}
};
export default ManualEditModal;
提前感谢您的帮助,我希望这可以完成......在这个问题上 2 周!
更新:截至目前,我尝试过(没有成功):
- 将 useMemo 钩子从数据常量中删除到表中,使其更频繁地重新呈现,但似乎并没有削减它。
- 将 props 中的数据作为新数组传递,并将旧数组传播到其中。