- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我无法在 Material 表中添加、更新或删除行。如果我将数据初始化为状态,那么它只会显示它,但无法编辑或删除它,我也无法将数据添加到表中。输入到表中的数据也会反射(reflect)在状态中,但是当组件在 setState 之后重新渲染时,它不会显示在表中。
官方网站上给出的代码也与我的行为方式相同。链接到官方网站上的示例: https://material-table.com/#/docs/features/editable
我创建了一个codesandbox供引用:https://codesandbox.io/s/material-demo-pqq3t?fontsize=14&hidenavigation=1&module=%2Fdemo.js&theme=dark
我无法得到的一件事是,当我初始化数据以声明一个新属性时,它会添加到数据中,即 tableData。但是,当我从表中添加状态数据时,该属性不会设置为这些对象
这是我的代码:`
state = {
openDialog: false,
nameOfCustomer: "",
date: new Date(),
items: [{ item: 'Mehmet', cost: 10, quantity: 7, total: null }],
tax: 0,
total: 0,
roundoff: 0,
columns: [
{ title: 'Item', field: 'item', },
{ title: 'Quantity', field: 'quantity', type: 'numeric', },
{ title: 'Cost/Item', field: 'cost', type: 'numeric', },
{ title: 'Total', field: 'total', type: 'numeric', editable: 'never' },
],
}
// componentDidUpdate(){
// // console.log(this.props.invoices)
// }
handleClose = () => {
this.setState({ openDialog: false })
}
feedDataIntoStore = () => {
const { nameOfCustomer, date, items } = this.state;
const storeData = { nameOfCustomer, date, items };
if (!nameOfCustomer || items.length === 0 || !date) this.setState({ openDialog: true });
// console.log(storeData);
this.props.dispatch(createInvoice(storeData));
}
handleItemListData = (data) => {
this.setState({ items: data.items, total: data.total, tax: data.tax, roundoff: data.roundoff })
}
handleNameChange = (e) => {
this.setState({ nameOfCustomer: e.target.value })
}
handleDateChange = newDate => {
this.setState({
date: newDate
})
};
render() {
const { classes } = this.props;
return (<React.Fragment>
<Container>
<Paper className={classes.root}>
<Typography variant="h5" component="h3">
Create Invoice
</Typography>
<Divider style={{ marginTop: 15, marginBottom: 15 }} />
<TextField
id="standard-full-width"
label="Name"
style={{ margin: 8 }}
placeholder="Name of Customer"
margin="normal"
fullWidth
value={this.state.nameOfCustomer}
onChange={this.handleNameChange}
InputLabelProps={{
shrink: true,
}}
/>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<KeyboardDatePicker
style={{ margin: 8, marginBottom: 20 }}
margin="normal"
id="date-picker-dialog"
label="Date picker dialog"
format="dd/MM/yyyy"
value={this.state.date}
onChange={this.handleDateChange}
KeyboardButtonProps={{
'aria-label': 'change date',
}}
/>
</MuiPickersUtilsProvider>
{console.log(this.state.items)}
<MaterialTable
title="Items"
enableRowDelete={true}
enableRowAdd={true}
columns={this.state.columns}
data={this.state.items}
editable={{
onRowAdd: newData =>
new Promise(resolve => {
setTimeout(() => {
resolve();
const newItems = this.state.items;
if (!newData.cost || !newData.quantity) {
this.setState({dialogOpen: true });
// handleDateChange({ items: state.items, total, tax, roundoff });
}
else {
let newtotal = 0, newtax = 0, newroundoff = 0;
newData.total = parseFloat((newData.cost * newData.quantity).toFixed(2));
newItems.push(newData);
newItems.forEach((item) => { newtotal = newtotal + parseFloat(item.total, 10) });
newtotal.toFixed(2);
newtax = parseFloat(((newtotal / 100) * 28).toFixed(2));
newroundoff = parseFloat((Math.round(newtotal + newtax) - (newtotal + newtax)).toFixed(2));
newtotal = parseInt(Math.round(newtotal + newtax));
this.setState({ items: newItems, tax: newtax, roundoff: newroundoff, total: newtotal });
}
}, 500);
}),
onRowUpdate: (newData, oldData) =>
new Promise(resolve => {
setTimeout(() => {
resolve();
if (oldData) {
const newItems = this.state.items;
if(!newData.cost || !newData.quantity)
this.setState({dialogOpen: true})
else{
let newtotal = 0, newtax = 0, newroundoff = 0;
newData.total = parseFloat((newData.cost * newData.quantity).toFixed(2));
newItems[newItems.indexOf(oldData)] = newData;
newItems.forEach((item) => { newtotal = newtotal + parseFloat(item.total, 10) });
newtotal.toFixed(2);
newtax = parseFloat(((newtotal / 100) * 28).toFixed(2));
newroundoff = parseFloat((Math.round(newtotal + newtax) - (newtotal + newtax)).toFixed(2));
newtotal = parseInt(Math.round(newtotal + newtax));
this.setState({ items: newItems, tax: newtax, roundoff: newroundoff, total: newtotal });
}
}
}, 500);
}),
onRowDelete: oldData =>
new Promise(resolve => {
setTimeout(() => {
resolve();
const newItems = this.state.items;
let newtotal = 0, newtax = 0, newroundoff = 0;
newItems.splice(newItems.indexOf(oldData), 1);
newItems.forEach((item) => { newtotal = newtotal + parseFloat(item.total, 10) });
newtotal.toFixed(2);
newtax = parseFloat(((newtotal / 100) * 28).toFixed(2));
newroundoff = parseFloat((Math.round(newtotal + newtax) - (newtotal + newtax)).toFixed(2));
newtotal = parseInt(Math.round(newtotal + newtax));
this.setState({ items: newItems, tax: newtax, roundoff: newroundoff, total: newtotal });
}, 500);
}),
}}
options={{
rowStyle: {
backgroundColor: '#EEE',
},
actionsColumnIndex: 3,
search: false,
minBodyHeight: 300,
loadingType: "linear",
}}
components={{
Cell: props => (
<MTableCell {...props} className={classes.noBorder} />
),
EditField: props => (
<MTableEditField {...props} className={classes.customWidth} />
),
Pagination: props => (
<TableCell colSpan={3} className={classes.footerFix}>
<Box component="span" m={1} className={classes.flex}>
<Typography variant="h6" component="span" align={"center"}>Tax Amount: </Typography>
<Typography variant="h6" component="span" align={"center"}>{this.state.tax}</Typography>
</Box>
<Divider variant="middle" />
<Box component="span" m={1} className={classes.flex}>
<Typography variant="h5" component="span" align={"center"}>Total Amount: </Typography>
<span style={{ display: "flex", flexDirection: "column", height: "3em", alignItems: "flex-end" }}>
<Typography variant="button" component="span" align={"center"}><span>Round off.</span> <span>{this.state.roundoff}</span></Typography>
<Typography variant="h5" component="span" align={"center"}>{this.state.total}</Typography>
</span>
</Box>
</TableCell>
),
}}
/>
<DisableFieldEditable />
<AlertDialog text = {"Please Enter All Data....."} title = {"Invalid Input"} open = {this.state.openDialog} handleClose = {this.handleClose}/>
<Button variant="contained" color="primary" className={classes.button} onClick={this.feedDataIntoStore}>
Create Invoice
</Button>
</Paper>
</Container>
<AlertDialog text={"You Need To Provide All The Data To Create Invoice, Fields Can't Be Kept Empty"} title={"Can't Create Invoice"} open={this.state.openDialog} handleClose={this.handleClose} />
</React.Fragment>);
}
`
最佳答案
您正在改变状态中的数据对象,而不是将其更新为不可变。
因此,react 会跳过重新渲染,新数据不会传递到表中。如果状态内所有对象的引用都相同在此之前,React 会提前退出。通过使用 data: [...data, newData]
创建一个新对象,您可以更改数据对象的引用,并且 React 将正确重新渲染。
改成这样就可以了:
new Promise((resolve, reject) => {
setTimeout(() => {
this.setState(prevState => ({
data: [...prevState.data, newData]
}), resolve);
}, 1000);
})
这只是 onRowAdd
的示例代码,需要针对 onRowUpdate
和 onRowDelete
进行更改。但这是总体思路。
这也适用于 useState 钩子(Hook),它会这样:
const [data, setData] = useState([]);
...
setData(prevData => [...prevData, newData])
关于reactjs - 无法使用基于类的组件添加、更新、删除 Material 表中的行。以前它与功能组件一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59473724/
我正在构建一个 RCP 应用程序,其中每个季度都会更新功能/插件。因此,如果用户选择自动更新功能/插件,则会下载更新插件的新 jar,但旧插件仍在使用我不再使用的磁盘空间。 我厌倦了删除包含旧 jar
我如何从外部 Controller 功能中调用 Controller 内部的功能,例如电话间隙回调功能 这是 Controller 外部定义的功能 function onDeviceReady()
如果某个功能(例如 MediaSource)可用,我如何使用 Google Dart 检查。 new MediaSource() 抛出一个错误。如何以编程方式检查此类或功能是否存在?有任何想法吗?是否
我正在尝试运行 Azure Orchestrations,突然我开始从 statusQueryGetUri 收到错误: 协调器函数“UploadDocumentOrchestrator”失败:函数“U
我见过 iPhone 上的应用程序,如果在 3.0 上运行,将使用 3.0 功能/API,例如应用内电子邮件编辑器,如果在 2.x 上运行,则不使用这些功能,并退出应用程序以启动邮件相反。 这是怎么做
这是 DB 规范化理论中的一个概念: Third normal form is violated when a non-key field is a fact about another non-ke
如果我定义 #if SOMETHING #endif 而且我还没有在任何地方定义 SOMETHING。 #if 中的代码会编译吗? 最佳答案 当#if的参数表达式中使用的名称未定义为宏时(在所有其他宏
我刚刚澄清了 A* 路径查找应该如何在两条路径具有相等值的 [情况] 下运行,无论是在计算期间还是在结束时,如果有两条相等的短路径。 例如,我在我的起始节点,我可以扩展到两个可能的节点,但它们都具有相
Java有没有类似下面的东西 宏 一种遍历所有私有(private)字段的方法 类似于 smalltalk symbols 的东西——即用于快速比较静态字符串的东西? 请注意,我正在尝试为 black
这个程序应该将华氏度转换为摄氏度: #include int main() { float fahrenheit, celsius; int max, min, step;
当打开PC缓存功能后, 软件将采用先进先出的原则排队对示波器采集的每一帧数据, 进行帧缓存。 当发现屏幕中有感兴趣的波形掠过时, 鼠标点击软件的(暂停)按钮, 可以选择回看某一帧的波形
我有一个特殊的(虚拟)函数,我想在沙盒环境中使用它: disable.system.call eval(parse(text = 'model.frame("1 ~ 1")'), envir = e
使用新的 Service 实现,我是否必须为我的所有服务提供一个 Options 方法? 使用我的所有服务当前使用的旧 ServiceBase 方法,OPTIONS 返回 OK,但没有 Access-
我正在阅读 Fogus 的关于 Clojure 的喜悦的书,在并行编程章节中,我看到了一个函数定义,它肯定想说明一些重要的事情,但我不知道是什么。此外,我看不到这个函数有什么用 - 当我执行时,它什么
我有大量的 C 代码,大部分代码被注释掉和/或 #if 0。当我使用 % 键匹配 if-else 的左括号和右括号时,它也匹配注释掉的代码。 有没有办法或vim插件在匹配括号时不考虑注释掉或#if 0
我有这个功能: map(map(fn x =>[x])) [[],[1],[2,3,4]]; 产生: val it = [[],[[1]],[[2],[3],[4]]] 我不明白这个功能是如何工作的。
我使用 Visual Studio 代码创建了一个函数应用程序,然后发布了它。功能应用程序运行良好。我现在在功能门户中使用代码部署功能(KUDU)并跳过构建。下面是日志 9:55:46 AM
我有一个数据框df: userID Score Task_Alpha Task_Beta Task_Charlie Task_Delta 3108 -8.00 Easy Easy
我真的无法解决这个问题: 我有一个返回数据框的函数。但是,数据框仅打印在我的控制台中,尽管我希望将其存储在工作空间中。我怎样才能做到这一点? 样本数据: n <- 32640 t <- seq(3*p
有没有办法找出所有可能的激活器命令行选项? activator -help仅提供最低限度的可用选项/功能列表,但所有好的东西都隐藏起来,即使在 typesafe 网站在线文档中也不可用。 到目前为止,
我是一名优秀的程序员,十分优秀!