gpt4 book ai didi

reactjs - 无法使用基于类的组件添加、更新、删除 Material 表中的行。以前它与功能组件一起工作

转载 作者:行者123 更新时间:2023-12-02 03:03:46 25 4
gpt4 key购买 nike

我无法在 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。但是,当我从表中添加状态数据时,该属性不会设置为这些对象 enter image description here
这是我的代码:`

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 的示例代码,需要针对 onRowUpdateonRowDelete 进行更改。但这是总体思路。

这也适用于 useState 钩子(Hook),它会这样:

const [data, setData] = useState([]);
...

setData(prevData => [...prevData, newData])

关于reactjs - 无法使用基于类的组件添加、更新、删除 Material 表中的行。以前它与功能组件一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59473724/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com