问题描述
由于某种原因,在我的代码中,每当我单击取消按钮时,disableAccount
按钮的 onClick
事件就会被激活.因此,取消将 isEditMode
设置为 false,但 disableAccount
将其设置回 true,从而阻止我在 UI 中看到任何明显的变化.这是一个 next.js 项目.
从'react'导入反应;从'../Input/TextInput'导入TextInput;从../Buttons/SmallButton"导入 SmallButton;const DisableAccountForm = ({t, tc, onSubmit, 密码, setPassword, isEditMode, setIsEditMode}) =>{返回 (<label className="block w-full max-w-xl text-2xl mb-4">{t(管理员")}<form onSubmit={onSubmit} className="w-full max-w-xl text-base mt-2><p className="mb-4">{t(禁用P")}</p>{是编辑模式?<p className="mb-4">{t(youSureP")}</p><p className="text-sm mb-4">{t("enterPasswordP")}</p></div>: 空值}{是编辑模式?<label className="flex-col">{tc(密码")}<文本输入占位符={tc(密码")}值={密码}onChange={e=>setPassword(e.target.value)}样式=m-1";必需的/>
这是上面代码的控制器.
import React, {useState} from 'react';从../components/DisableAccountForm/DisableAccountForm"导入 DisableAccountForm;const DisableAccountController = ({t, tc, onSubmit}) =>{const [密码, setPassword] = useState("");const [isEditMode, setIsEditMode] = useState(false);const disableAccount = (e) =>{e.preventDefault();console.log("disableAccount");setIsEditMode(false);}返回 (
小按钮
从'react'导入反应;const SmallButton = ({type, label, color, textColor, style, onClick}) =>{返回 (
解决方案
TL;DR
TL;DR
问题在于
label
包装器点击";在表单从编辑模式切换到显示模式后立即禁用帐户按钮.这是 HTML label
元素的默认行为.您可以通过将 label
更改为 div
或片段或任何其他不单击按钮的包装器来解决它.
详细解释
详细解释
转到您发布的沙盒.它以显示模式(不是编辑模式)打开.现在,按文本Admin";在顶端.如您所见,禁用帐户"按钮被按下 - 肯定不是预期的行为.
发生这种意外行为的原因与取消按钮切换回编辑模式的原因相同.整个问题是关于包装表单的
label
.HTML 原生 label
元素 将 label
附近或内部的可点击元素之一的点击事件附加到 label
内部的内容.在显示模式下,label
检测到禁用帐户";按钮并将其单击事件附加到整个组件.
因此,当您单击取消"时按钮 - 组件切换到编辑模式,
label
包装器点击";禁用帐户"按钮并将其切换回编辑模式.提交表单时您看不到它,因为您在 onSubmit
回调中阻止了 label
的默认行为.您的问题的部分解决方案也可以是 preventDefault
在取消回调中 - 但它会使文本可点击.另一种解决方案可能是将 label
更改为 div
或片段或任何其他不单击按钮的包装器.
For some reason, in my code the
onClick
event for the disableAccount
button gets activated whenever I click the cancel button. So cancel sets isEditMode
to false but disableAccount
sets it back to true thus preventing me from seeing any noticeable change in my UI. This is a next.js project.
import React from 'react';
import TextInput from '../Input/TextInput';
import SmallButton from '../Buttons/SmallButton';
const DisableAccountForm = ({t, tc, onSubmit, password, setPassword, isEditMode, setIsEditMode}) => {
return (
<label className="block w-full max-w-xl text-2xl mb-4">
{t("admin")}
<form onSubmit={onSubmit} className="w-full max-w-xl text-base mt-2">
<p className="mb-4">
{t("disableP")}
</p>
{isEditMode ?
<div>
<p className="mb-4">
{t("youSureP")}
</p>
<p className="text-sm mb-4">
{t("enterPasswordP")}
</p>
</div>
: null
}
{isEditMode ?
<label className="flex-col">
{tc("password")}
<TextInput
placeholder={tc("password")}
value={password}
onChange={e=>setPassword(e.target.value)}
style="m-1"
required
/>
<SmallButton
type="submit"
label={tc("submit")}
color='bg-blue-500'
textColor='text-white'
/>
<SmallButton
type="button"
label={tc("cancel")}
color='bg-red-500'
textColor='text-white'
onClick={() => {console.log("cancel"); setIsEditMode(false)}}
/>
</label>
:
<SmallButton
type="button"
label={t("disableAccount")}
color='bg-blue-500'
textColor='text-white'
onClick={() => {console.log("why"); setIsEditMode(true)}}
/>
}
</form>
</label>
);
}
export default DisableAccountForm;
This is the controller for the code above.
import React, {useState} from 'react';
import DisableAccountForm from '../components/DisableAccountForm/DisableAccountForm';
const DisableAccountController = ({t, tc, onSubmit}) => {
const [password, setPassword] = useState("");
const [isEditMode, setIsEditMode] = useState(false);
const disableAccount = (e) => {
e.preventDefault();
console.log("disableAccount");
setIsEditMode(false);
}
return (
<DisableAccountForm
t={t}
tc={tc}
onSubmit={disableAccount}
password={password}
setPassword={setPassword}
isEditMode={isEditMode}
setIsEditMode={setIsEditMode}
/>
);
}
export default DisableAccountController;
SmallButton
import React from 'react';
const SmallButton = ({type, label, color, textColor, style, onClick}) => {
return (
<button
type={type}
className={`m-1 ${color} hover:ring-2 rounded-md px-2 py-1 min-w-20 ${textColor} ${style}`}
onClick={onClick}
>
{label}
</button>
);
}
export default SmallButton;
解决方案
TL;DR
TL;DR
The problem is that the
label
wrapper "clicks" the Disable account button right after the form is switched from edit to display mode. It is the default behaviour of HTML label
elements. You can solve it by changing the label
to div
or fragment or any other wrapper that does not click your buttons.
Explain In Details
Explain In Details
Go to the sandbox you have posted. It opens in display mode (not edit mode). Now, press the text "Admin" on the top. As you can see, the "Disable account" button is pressed - surely not the expected behaviour.
This unexpected behaviour happens for the same reason that the cancel button switches back to edit mode. the whole problem is about the
label
that wraps the form. The HTML native label
element attaches the click event of one of the clickable elements nearby or inside the label
to the content inside the label
. In-display mode, the label
detect the "Disable account" button and attach its click event to the whole component.
So, when you click the "cancel" button - the component switches to edit mode, and the
label
wrapper "clicks" the "Disable account" button and switches it back to edit mode. You don't see it when submitting the form, because you prevent the label
's default behaviour in onSubmit
callback. A partial solution for your problem can be to preventDefault
in the cancel callback too - but it will leave the texts clickable. Another solution might be to change the label
to div
or fragment or any other wrapper that does not click your buttons.
这篇关于OnClick 触发另一个按钮单击事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!