英文:
React: My App reloads after I click the button
问题
在我的应用程序中,以下是我编写的组件代码。在这个组件中,我正在渲染一个表单,该表单还包含一个动态生成的表格。问题是,当我点击删除按钮以删除表格中的条目时,我的应用程序重新加载,这不是我想要的行为。
import { ChangeEvent, useState } from 'react';
import { AssetData } from '../../models/asset.model';
export default function CreateAsset() {
const [assetData, setAssetData] = useState<AssetData>({
assetId: "",
metaData: [
{ "key": "", "value": "" }
]
});
const handleChange = (event: { target: { name: any; value: any; }; }) => {
const { name, value } = event.target;
setAssetData((prevAssetData) => ({ ...prevAssetData, [name]: value }));
console.log(assetData);
};
const updateMetaData = (event: ChangeEvent<HTMLInputElement>, idx: number) => {
const { name, value } = event.target;
setAssetData((prevAssetData) => {
const newAssetData = { ...prevAssetData, metaData: [...prevAssetData.metaData] }
const updatedMetaDataEntry = { ...newAssetData.metaData[idx], [name]: value }
newAssetData.metaData[idx] = updatedMetaDataEntry
return newAssetData;
});
};
const handleAddMetaData = () => {
setAssetData((prevAssetData) => {
const newAssetData = { ...prevAssetData, metaData: [...prevAssetData.metaData, { "key": "", "value": "" }] }
return newAssetData;
});
};
const handleRemoveMetaData = (idx: number) => {
setAssetData((prevAssetData) => {
const newAssetData = { ...prevAssetData, metaData: [...prevAssetData.metaData] }
newAssetData.metaData.splice(idx, 1)
return newAssetData;
});
};
return (
<form>
<label htmlFor="assetId">Asset ID:</label>
<input type="text" id="assetId" name="assetId" value={assetData.assetId} onChange={handleChange} />
<br /><br />
<label>MetaData:</label>
<table>
<thead>
<tr>
<th>Key</th>
<th>Value</th>
<th></th>
</tr>
</thead>
<tbody>
{assetData.metaData.map((item, idx) => (
<tr key={idx}>
<td><input type="text" name="key" value={item.key} onChange={(e) => updateMetaData(e, idx)} /></td>
<td><input type="text" name="value" value={item.value} onChange={(e) => updateMetaData(e, idx)} /></td>
{assetData.metaData.length !== 1 && <td><button onClick={(e) => { handleRemoveMetaData(idx) }}>Remove</button></td>}
{assetData.metaData.length - 1 === idx && <td><button onClick={handleAddMetaData}>Add</button></td>}
</tr>
))}
</tbody>
</table>
</form>
);
};
当我点击“删除”按钮时,只应删除该表格行,但在我的情况下,整个组件重新加载。我还注意到了一件事,就是在与删除按钮附加的onClick回调中,如果我添加e.preventDefault()
语句,我的代码就会按预期工作,只有该表格行被删除。有人可以指导我这种奇怪行为的原因吗?
英文:
Below is the code of the component that I have written in my application. In this component, I am rendering a form that also has a table which is dynamically generated. The problem is that when I click on the remove button to delete the entry of a table in the form, my app reloads that is not the desired behaviour that I want.
import {ChangeEvent, useState} from 'react';
import { AssetData } from '../../models/asset.model';
export default function CreateAsset() {
const [assetData, setAssetData] = useState<AssetData>({assetId: "", metaData: [
{"key": "", "value": ""}]});
const handleChange = (event: { target: { name: any; value: any; }; }) => {
const { name, value } = event.target;
setAssetData((prevAssetData) => ({ ...prevAssetData, [name]: value }));
console.log(assetData);
};
const updateMetaData = (event: ChangeEvent<HTMLInputElement>, idx: number) => {
const { name, value } = event.target;
setAssetData((prevAssetData) => {
const newAssetData = { ...prevAssetData, metaData: [...prevAssetData.metaData ] }
const updatedMetaDataEntry = { ...newAssetData.metaData[idx], [name]: value }
newAssetData.metaData[idx] = updatedMetaDataEntry
return newAssetData;
});
};
const handleAddMetaData = () => {
setAssetData((prevAssetData) => {
const newAssetData = { ...prevAssetData, metaData: [...prevAssetData.metaData, {"key": "", "value": ""}] }
return newAssetData;
});
};
const handleRemoveMetaData = (idx: number) => {
setAssetData((prevAssetData) => {
const newAssetData = { ...prevAssetData, metaData: [...prevAssetData.metaData ] }
newAssetData.metaData.splice(idx, 1)
return newAssetData;
});
};
return (
<form>
<label htmlFor="assetId">Asset ID:</label>
<input type="text" id="assetId" name="assetId" value={assetData.assetId} onChange={handleChange}/>
<br></br>
<label >MetaData:</label>
<table>
<thead>
<tr>
<th>Key</th>
<th>Value</th>
<th></th>
</tr>
</thead>
<tbody>
{assetData.metaData.map((item, idx) => (
<tr key={idx}>
<td><input type="text" name="key" value={item.key} onChange={(e) => updateMetaData(e, idx)}/></td>
<td><input type="text" name="value" value={item.value} onChange={(e) => updateMetaData(e, idx)}/></td>
{assetData.metaData.length !== 1 && <td><button onClick={(e) =>
{handleRemoveMetaData(idx)}}>Remove</button></td>}
{assetData.metaData.length - 1 === idx && <td><button onClick={handleAddMetaData}>Add</button></td>}
</tr>
))}
</tbody>
</table>
</form>
)};
When I should click on the Remove
button, only that table row should be deleted but in my case the entire component reloads. I have noticed one more thing. In the onClick callback attached to the Remove button, if I add e.preventDefault()
statement, my code works as expected and only that table row is deleted. Can anyone guide me what is the reason of the strange behaviour.
答案1
得分: 3
在与“删除”按钮关联的onClick回调中,如果我添加e.preventDefault()
语句,我的代码将按预期工作,只删除该表格行。
这是解决问题的一种方法,是的。您所经历的不是奇怪的行为,而是默认的行为。
除非另有规定,<button>
元素的默认type
是submit
。而且在您的<button>
元素中未指定type
。所以它们是submit
按钮。
此外,没有明确action
的<form>
将提交到当前URL。
将这些放在一起,您拥有的是提交表单的按钮,除了重新加载当前页面之外什么也不做。
更改此行为的其他选项包括:
- 将
type="button"
添加到按钮 - 如果您不打算对其进行任何操作,完全删除
<form>
元素
英文:
> In the onClick callback attached to the Remove button, if I add e.preventDefault()
statement, my code works as expected and only that table row is deleted.
That's one way to solve the problem, yes. What you're experiencing is not strange behavior, it's default behavior.
Unless otherwise specified, the default type
for a <button>
element is submit
. And the type
is not specified in your <button>
elements. So they're submit
buttons.
Additionally, a <form>
with no explicit action
will submit to the current URL.
Put these together and what you have are buttons which submit your form, doing nothing more than reloading the current page.
Other options to change this behavior include:
- Add
type="button"
to the buttons - Remove the
<form>
element entirely if you're not planning to use it for anything
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论