我有一个使用 devextreme 代码块进行 React 的代码,其中包含多个字段。两个按钮,一个添加新行,一个删除其相应的行。由于我的组件每次更改时都会发送数据,而无需任何按钮,因此我使用 onBlur 来通过双击来更改状态。但我的用户希望它们一键更新。那么有什么方法可以执行此特定操作。 我的代码
import React, { useState, useEffect } from "react";
import apis from "../api-constants";
import './temporarystack.scss';
import DataGrid, { Column } from "devextreme-react/data-grid";
import useGetAPI from "../getAPIS";
import { Button, SelectBox } from "devextreme-react";
import { formatMessage } from "devextreme/localization";
function TemporaryStack({ tokenDetails, operation, isTempUsed, temporaryStacksJSON }) {
const [showTable, setShowTable] = useState(false);
const [listData, setListData] = useState([{
shed: '',
storageType: '',
assignedBags: '',
fcapacity: '',
maxBags: '',
lead: '',
bagsPerLayer: '',
location: '',
comment: '',
}]);
const [shedOptions, setShedOptions] = useState(null);
const [threshold, setThreshold] = useState({})
const storageTypeOptions = [
{ id: 1, name: 'Gangway' },
{ id: 2, name: 'Alleyway' },
{ id: 3, name: 'Road Side' },
{ id: 4, name: 'Plinth' },
{ id: 5, name: 'Other' }
]
useEffect(() => {
async function Dataapi() {
const responceforshed = await useGetAPI(apis.GET_GODOWN_UNITS(operation))
const responceforthreshold = await useGetAPI(apis.GET_BAGWEIGHT_THRESHOLD_MAXIMUXBAGCAPACITY)
setShedOptions(responceforshed.data)
setThreshold(responceforthreshold.data)
}
if (showTable === true) {
Dataapi()
}
}, [operation, tokenDetails, showTable])
useEffect(() => {
temporaryStacksJSON(listData.map(obj=>{
const {fcapacity,storageType,location,comment,bagsPerLayer,assignedBags,lead,maxBags,shed}=obj
return {
fcapacity:fcapacity,
storageType:storageType,
location:location,
comment:comment,
bagsPerLayer:bagsPerLayer,
assignedBags:assignedBags,
flagRecordExists:true,
isTemporaryStackUsed:true,
lead:lead,
maxBags:maxBags,
mappedGenericId:tokenDetails.genericid,
mappedGodownUnitId:shed
}
}))
}, [listData])
// removing data when Temporary stack is unchecked and initialization state
const handleCheckboxChange = (e) => {
const isChecked = e.target.checked;
setShowTable(isChecked);
isTempUsed(isChecked)
if (!isChecked) {
setListData([])
}
};
// adding new row to the temporary stack
const addRow = () => {
const newItem = {
shed: shedOptions && shedOptions.length > 0 ? shedOptions[0]?.value : '',
storageType: storageTypeOptions.length > 0 ? storageTypeOptions[0].name : '',
assignedBags: '',
fcapacity: '',
maxBags: '',
lead: '',
bagsPerLayer: '',
location: '',
comment: '',
};
setListData((prevList) => [...prevList, newItem]);
};
// to delete a temporary stack
const deleteRow = (index) => {
const updatedList = [...listData];
updatedList.splice(index, 1);
setListData(updatedList);
};
const DataRow = (rowInfo) => (
<>
<tr className="main-row">
<td>
{rowInfo.rowIndex + 1}
</td>
<td >
<SelectBox
dataSource={shedOptions}
displayExpr={'value'}
valueExpr={'id'}
onValueChange={e => {
const updatedList = [...listData];
updatedList[rowInfo.rowIndex].shed = e;
setListData(updatedList);
}}
value={rowInfo.data.shed}
defaultValue={rowInfo.data.shed}
/>
</td>
<td>
<SelectBox
dataSource={storageTypeOptions}
displayExpr="name"
valueExpr="name"
onValueChanged={e => {
const updatedList = [...listData];
updatedList[rowInfo.rowIndex].storageType = e.value;
setListData(updatedList);
}}
value={rowInfo.data.storageType}
defaultValue={rowInfo.data.storageType}
/>
</td>
<td>
<input
type="number"
defaultValue={rowInfo.data.assignedBags}
onBlur={(e) => {
const updatedList = [...listData];
updatedList[rowInfo.rowIndex].assignedBags = parseInt(e.target.value)
setListData(updatedList);
}}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
}}
/>
</td>
<td>
<input
type="number"
defaultValue={rowInfo.data.fcapacity}
onBlur={(e) => {
const updatedList = [...listData];
updatedList[rowInfo.rowIndex].fcapacity = parseInt(e.target.value)
setListData(updatedList);
}}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
}}
/>
</td>
<td>
<input
type="number"
defaultValue={rowInfo.data.maxBags}
onBlur={(e) => {
const updatedList = [...listData];
updatedList[rowInfo.rowIndex].maxBags = parseInt(e.target.value)
setListData(updatedList);
}}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
}}
/>
</td>
<td>
<input
type="number"
defaultValue={rowInfo.data.lead}
onBlur={(e) => {
const updatedList = [...listData];
updatedList[rowInfo.rowIndex].lead = parseInt(e.target.value)
setListData(updatedList);
}}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
}}
/>
</td>
<td>
<input
type="number"
defaultValue={rowInfo.data.bagsPerLayer}
onBlur={(e) => {
const updatedList = [...listData];
updatedList[rowInfo.rowIndex].bagsPerLayer = parseInt(e.target.value)
setListData(updatedList);
}}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
}}
/>
</td>
<td>
<Button
icon="close"
onClick={() => deleteRow(rowInfo.rowIndex)}
style={{
borderRadius: '10%',
padding: 0,
width: '20px',
height: '20px',
minWidth: '20px',
minHeight: '20px',
lineHeight: '20px',
}}
/>
</td>
</tr>
<tr>
<td></td>
<td colSpan={2}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div>{formatMessage('LocationDescription')}</div>
<textarea
defaultValue={rowInfo.data.location}
maxLength="25"
onBlur={(e) => {
const updatedList = [...listData];
updatedList[rowInfo.rowIndex].location = (e.target.value)
setListData(updatedList);
}}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
}}
/>
</div>
</td>
<td colSpan={2}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ marginRight: '10px' }}>{formatMessage('Commentl')}</div>
<textarea
defaultValue={rowInfo.data.comment}
maxLength="250"
onBlur={(e) => {
const updatedList = [...listData];
updatedList[rowInfo.rowIndex].comment = (e.target.value)
setListData(updatedList);
}}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
}}
/>
</div>
</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</>
);
// rendering the table or state change for data
const renderTable = () => {
if (!showTable) return null;
return (
<>
<DataGrid dataSource={listData} showBorders={true} dataRowRender={DataRow}>
<Column width={25} />
<Column caption={formatMessage("Shed")} />
<Column caption={formatMessage('StorageType')} />
<Column dataField="assignedBags" caption={formatMessage("AssignedBagInTemp")} />
<Column dataField="fcapacity" caption={formatMessage('Capacity')} />
<Column dataField="maxBags" caption={formatMessage('MaxBags')} />
<Column dataField="lead" caption={formatMessage("Lead")} />
<Column dataField="bagsPerLayer" caption={formatMessage('BagsPerLayer')} />
<Column width={35} />
</DataGrid>
<Button
onClick={addRow}
icon="plus"
className="small-button"
style={{
borderRadius: '10%',
marginTop: '5px',
padding: 0,
width: '20px',
height: '20px',
minWidth: '20px',
minHeight: '20px',
lineHeight: '20px',
}}
/>
</>
);
};
return (
<>
<label>
<input type="checkbox" onChange={(e) => handleCheckboxChange(e)} />
{formatMessage('TemporaryStack')}
</label>
{renderTable()}
</>
);
};
export default React.memo(TemporaryStack)
我曾尝试使用 onChange,但它正在更新每个字符,并且 Changeevent 无效。该表格的另一件事是用复选框括起来。
要在 React 中使用 DevExtreme 组件实现一键更新,请从使用
onBlur
切换到 onChange
。此调整可确保您的状态在值更改后立即更新,而不仅仅是在元素失去焦点时更新。如果您的更新是资源密集型的,请记住管理和消除快速的状态变化,以保持性能。此策略通过将状态更改直接链接到用户操作而不需要额外的单击来提供响应更快的用户体验。