React:点击按钮后,我的应用程序重新加载

huangapple go评论81阅读模式
英文:

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 &#39;react&#39;;
import { AssetData } from &#39;../../models/asset.model&#39;;
export default function  CreateAsset()  {
const  [assetData, setAssetData] =  useState&lt;AssetData&gt;({assetId: &quot;&quot;, metaData: [
{&quot;key&quot;: &quot;&quot;, &quot;value&quot;: &quot;&quot;}]});
const handleChange = (event: { target: { name: any; value: any; }; }) =&gt; {
const { name, value } = event.target;
setAssetData((prevAssetData) =&gt; ({ ...prevAssetData, [name]: value }));
console.log(assetData);
};
const updateMetaData = (event: ChangeEvent&lt;HTMLInputElement&gt;, idx: number) =&gt; {
const { name, value } = event.target;
setAssetData((prevAssetData) =&gt; {
const newAssetData = { ...prevAssetData, metaData: [...prevAssetData.metaData  ] }
const updatedMetaDataEntry =  { ...newAssetData.metaData[idx], [name]: value }
newAssetData.metaData[idx] = updatedMetaDataEntry
return newAssetData;
});
};
const handleAddMetaData = () =&gt; {
setAssetData((prevAssetData) =&gt; {
const newAssetData = { ...prevAssetData, metaData: [...prevAssetData.metaData, {&quot;key&quot;: &quot;&quot;, &quot;value&quot;: &quot;&quot;}] }
return newAssetData;
});
};
const handleRemoveMetaData = (idx: number) =&gt; {
setAssetData((prevAssetData) =&gt; {
const newAssetData = { ...prevAssetData, metaData: [...prevAssetData.metaData  ] }
newAssetData.metaData.splice(idx, 1)
return newAssetData;
});
};
return  (
&lt;form&gt;
&lt;label htmlFor=&quot;assetId&quot;&gt;Asset ID:&lt;/label&gt;
&lt;input type=&quot;text&quot; id=&quot;assetId&quot; name=&quot;assetId&quot; value={assetData.assetId} onChange={handleChange}/&gt;
&lt;br&gt;&lt;/br&gt;
&lt;label &gt;MetaData:&lt;/label&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
{assetData.metaData.map((item, idx) =&gt; (
&lt;tr key={idx}&gt;
&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;key&quot; value={item.key} onChange={(e) =&gt; updateMetaData(e, idx)}/&gt;&lt;/td&gt;
&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;value&quot; value={item.value} onChange={(e) =&gt; updateMetaData(e, idx)}/&gt;&lt;/td&gt;
{assetData.metaData.length !== 1 &amp;&amp; &lt;td&gt;&lt;button onClick={(e) =&gt; 
{handleRemoveMetaData(idx)}}&gt;Remove&lt;/button&gt;&lt;/td&gt;}
{assetData.metaData.length - 1 === idx &amp;&amp; &lt;td&gt;&lt;button onClick={handleAddMetaData}&gt;Add&lt;/button&gt;&lt;/td&gt;}
&lt;/tr&gt;
))}
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/form&gt;
)};

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>元素的默认typesubmit。而且在您的<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 &lt;button&gt; element is submit. And the type is not specified in your &lt;button&gt; elements. So they're submit buttons.

Additionally, a &lt;form&gt; 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=&quot;button&quot; to the buttons
  • Remove the &lt;form&gt; element entirely if you're not planning to use it for anything

huangapple
  • 本文由 发表于 2023年6月16日 01:43:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76484246.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定