如果我将组件放在我的标签中,则无法选择下拉选项
Dropdown option cannot be selected if I put the component inside my label
为什么当我将 Dropdown
组件放入 <label>
标签中时,它不起作用?下拉列表显示选项,但如果您单击其中一个,则选择不是 working/displayed。
有什么建议吗?
export default function App() {
return (
<div>
<div className="mt-10 mb-3 h-6 text-md uppercase font-bold>
People
</div>
<button type="button" onClick={addInvitee}>
+Add menu
</button>
<form onSubmit={handleSubmit}>
{invited.map(({ age, email, id, location, name }, index) => (
<div key={id}>
<div className="grid grid-cols-3 gap-5">
<label className="mr-3 h-6 text-md font-bold">
Names:
<input
type="text"
value={name}
placeholder="Names"
name="name"
onChange={updateInvitee(id)}
/>
</label>
//other inputs with the exact same pattern
<label>
Choice:
<Dropdown className="w-3/5" options={CHOICE} isMulti={false} />
</label>
...//other inputs
</form>
</div>
);
}
Dropdown.jsx
import React, { useState } from "react";
import Select from "react-select";
import Tag from "./Tag";
export default function Dropdown({
className,
style,
options,
styleSelect,
defaultValue,
isMulti = false
}) {
const [selected, setSelected] = useState(defaultValue);
const styles = {
select: {
width: "100%",
maxWidth: 200
}
};
return (
<div style={style}>
{selected && isMulti === false ? (
<Tag
selected={selected}
setSelected={setSelected}
styleSelect={styleSelect}
/>
) : (
<Select
className={className}
style={styles.select}
value={selected}
onChange={setSelected}
options={options}
isMulti={isMulti}
/>
)}
</div>
);
}
这是我的CodeSandbox
首先要注意以下几点:
基于此图像,来自沙箱的控制台片段,它显示 selection 发生,但立即被清除。
这是什么原因?嗯..让我们看看。
考虑这个代码片段:
<label>
Press the text
<br /><br />
<button onClick="console.log('button-clicked')">Button</button>
</label>
在这里,<button>
被放置在 <label>
中。您是否注意到,当您单击 press the text
时,button
的 onClick
会被触发? ...但是为什么?
嗯,默认情况下,<label>
是一个可获得焦点的 html 元素,当获得焦点时,它会触发放置在其中的任何表单控件元素。
那么这与您的代码有什么关系?
您的 <Tag>
组件 onClick={() => setSelected(null)}
中有这行代码,这就是问题所在。当你选择一个 selection 时,selected
得到更新,组件 re-renders 并显示你的 <Tag>
组件......但是事件仍然再次冒泡树直到它到达<label>
元素。请记住,此时显示的不再是 <Select>
组件,而是 <Tag>
组件。你猜怎么着? <label>
获得焦点并触发 <Tag>
组件内的 <button>
,该组件清除 (setSelected(null)
) selected
状态 属性。 selected
清除后,<Dropdown>
分量re-renders和<Select>
分量再次显示。
当您尝试 select 时,这种情况会一直持续下去,然后重复该过程。
所以,从您的代码中...只需在此处删除它 onClick={() => setSelected(null)}
,您就会发现它会起作用。所以你只需要解决如何清除 selected
,但我在下面提出了一个解决方案。
解决方案
在您的 <Dropdown>
组件中,我们应该尝试防止事件冒泡。因此,您需要做的就是在 <div>
中添加以下 onClick={e=>e.preventDefault()}
<div style={style} onClick={(e) => e.preventDefault()}>
{selected && isMulti === false ? (
<Tag
selected={selected}
setSelected={setSelected}
styleSelect={styleSelect}
/>
) : (
<Select
className={className}
style={styles.select}
value={selected}
onChange={setSelected}
options={options}
isMulti={isMulti}
/>
)}
</div>
为什么当我将 Dropdown
组件放入 <label>
标签中时,它不起作用?下拉列表显示选项,但如果您单击其中一个,则选择不是 working/displayed。
有什么建议吗?
export default function App() {
return (
<div>
<div className="mt-10 mb-3 h-6 text-md uppercase font-bold>
People
</div>
<button type="button" onClick={addInvitee}>
+Add menu
</button>
<form onSubmit={handleSubmit}>
{invited.map(({ age, email, id, location, name }, index) => (
<div key={id}>
<div className="grid grid-cols-3 gap-5">
<label className="mr-3 h-6 text-md font-bold">
Names:
<input
type="text"
value={name}
placeholder="Names"
name="name"
onChange={updateInvitee(id)}
/>
</label>
//other inputs with the exact same pattern
<label>
Choice:
<Dropdown className="w-3/5" options={CHOICE} isMulti={false} />
</label>
...//other inputs
</form>
</div>
);
}
Dropdown.jsx
import React, { useState } from "react";
import Select from "react-select";
import Tag from "./Tag";
export default function Dropdown({
className,
style,
options,
styleSelect,
defaultValue,
isMulti = false
}) {
const [selected, setSelected] = useState(defaultValue);
const styles = {
select: {
width: "100%",
maxWidth: 200
}
};
return (
<div style={style}>
{selected && isMulti === false ? (
<Tag
selected={selected}
setSelected={setSelected}
styleSelect={styleSelect}
/>
) : (
<Select
className={className}
style={styles.select}
value={selected}
onChange={setSelected}
options={options}
isMulti={isMulti}
/>
)}
</div>
);
}
这是我的CodeSandbox
首先要注意以下几点:
基于此图像,来自沙箱的控制台片段,它显示 selection 发生,但立即被清除。
这是什么原因?嗯..让我们看看。
考虑这个代码片段:
<label>
Press the text
<br /><br />
<button onClick="console.log('button-clicked')">Button</button>
</label>
在这里,<button>
被放置在 <label>
中。您是否注意到,当您单击 press the text
时,button
的 onClick
会被触发? ...但是为什么?
嗯,默认情况下,<label>
是一个可获得焦点的 html 元素,当获得焦点时,它会触发放置在其中的任何表单控件元素。
那么这与您的代码有什么关系?
您的 <Tag>
组件 onClick={() => setSelected(null)}
中有这行代码,这就是问题所在。当你选择一个 selection 时,selected
得到更新,组件 re-renders 并显示你的 <Tag>
组件......但是事件仍然再次冒泡树直到它到达<label>
元素。请记住,此时显示的不再是 <Select>
组件,而是 <Tag>
组件。你猜怎么着? <label>
获得焦点并触发 <Tag>
组件内的 <button>
,该组件清除 (setSelected(null)
) selected
状态 属性。 selected
清除后,<Dropdown>
分量re-renders和<Select>
分量再次显示。
当您尝试 select 时,这种情况会一直持续下去,然后重复该过程。
所以,从您的代码中...只需在此处删除它 onClick={() => setSelected(null)}
,您就会发现它会起作用。所以你只需要解决如何清除 selected
,但我在下面提出了一个解决方案。
解决方案
在您的 <Dropdown>
组件中,我们应该尝试防止事件冒泡。因此,您需要做的就是在 <div>
onClick={e=>e.preventDefault()}
<div style={style} onClick={(e) => e.preventDefault()}>
{selected && isMulti === false ? (
<Tag
selected={selected}
setSelected={setSelected}
styleSelect={styleSelect}
/>
) : (
<Select
className={className}
style={styles.select}
value={selected}
onChange={setSelected}
options={options}
isMulti={isMulti}
/>
)}
</div>