admin管理员组文章数量:1413471
I am using react-select to display a CreatableSelect dropdown. This drop down is controlled using react-hook-form. I have implemented the onCreateOption handler on the CreatableSelect. My handler then shows a Modal (React Bootstrap) which allows the user to fill in all details and then save the item. This modal component then calls a function as supplied to it, allowing the select component to listen for changes. Basically, the item to be added is saved successfully and the ID for this item is returned (which can be optimized, but that is beside the point for now).
This is my onCreateItem function;
const onCreateItem = (itemID: string) => {
setCreatingItem(false); // hide the modal
fetchReference(field.referencedModuleIdx, itemID).
then((reference) => {
let option: IconSelectOption = {
value: reference.id, id: reference.id, label: reference.name, iconUrl: reference.iconUrl
}
setOptions((options) => [...options, option]);
setSelectedValue(option); //no ?
setValue("inputfield-" + field.index, option); //no ?
}
);
}
The component in question looks as follows:
return (
<>
{creatingItem === true && <ItemCreateModal show={creatingItem} moduleIdx={field.referencedModuleIdx} onCreateItem={onCreateItem} value={input} />}
<Controller
name={"inputfield-" + field.index}
key={"inputfield-" + field.index}
defaultValue={selectedValue}
rules={{ required: field.required }}
render={renderProps => {
return (
<CreatableSelect
className="react-select-container"
classNamePrefix="react-select"
options={options}
isClearable
isSearchable
placeholder="..."
isDisabled={field.readOnly}
components={{ Option: IconOption, Control }}
{...register("inputfield-" + field.index)}
{...renderProps.field}
onCreateOption={(value) => handleCreateOption(value)}
onChange={e => {
setSelectedValue(e as IconSelectOption);
renderProps.field.onChange(e);
}}
/>
);
}}
/>
</>
)
and has the following defined:
const [creatingItem, setCreatingItem] = useState(false);
const [options, setOptions] = useState<IconSelectOption[]>(getOptions());
const [selectedValue, setSelectedValue] = useState<IconSelectOption>(getCurrentValue());
const [input, setInput] = useState("");
const { setValue } = useForm();
const { register } = useFormContext();
And that is where I get stuck;
- I do get the item added to the list of options; its actively showing and I can select it.
- But, I cannot make it the selected value.
I am still pretty new to React. I thought that I could get the select to be refreshed/updated either via the state controlled value selectedValue or either via setValue from the react-hook-form. But whatever I do, the old selected value remains selected and the new value is sitting in the list but remains unselected.
Can anyone point me in the right direction?
For references, the whole piece of code:
import { components, type ControlProps, type GroupBase, type OptionProps } from 'react-select'
import CreatableSelect from 'react-select/creatable';
import type { JSX } from 'react/jsx-runtime';
import { useState } from 'react';
import type { InputFieldComponentProps } from './dc_input_field';
import { useFormContext, Controller, useForm } from 'react-hook-form';
import { ItemCreateModal } from '../../pages/item/item_create_modal';
import { fetchReference, type Reference } from '../../services/datacrow_api';
export interface IconSelectOption {
value: string;
label: string;
iconUrl: string;
id: string;
}
const { Option } = components;
const IconOption = (props: JSX.IntrinsicAttributes & OptionProps<IconSelectOption, boolean, GroupBase<IconSelectOption>>) => (
<Option {...props}>
{props.data.iconUrl && (
<img
src={props.data.iconUrl}
key={props.data.iconUrl}
style={{ width: "24px", paddingRight: "8px" }}
/>
)}
{props.data.label}
</Option>
);
export default function DcReferenceField({
field,
value,
references
}: InputFieldComponentProps) {
const [creatingItem, setCreatingItem] = useState(false);
const [options, setOptions] = useState<IconSelectOption[]>(getOptions());
const [selectedValue, setSelectedValue] = useState<IconSelectOption>(getCurrentValue());
const [input, setInput] = useState("");
const { setValue } = useForm();
const { register } = useFormContext();
function getCurrentValue() {
let idx = 0;
let selectedIdx = -1;
options.forEach((option) => {
if (option.value === (value as Reference).id)
selectedIdx = idx;
idx++;
});
return options[selectedIdx];
}
const handleCreateOption = (value: string) => {
setInput(value);
setCreatingItem(true);
}
const onCreateItem = (itemID: string) => {
setCreatingItem(false); // hide the modal
fetchReference(field.referencedModuleIdx, itemID).
then((reference) => {
let option: IconSelectOption = {
value: reference.id, id: reference.id, label: reference.name, iconUrl: reference.iconUrl
}
setOptions((options) => [...options, option]);
setSelectedValue(option); //no ?
setValue("inputfield-" + field.index, option); //no ?
}
);
}
function getOptions() {
let options: IconSelectOption[] = [];
if (references && references.items) {
references.items.map(reference =>
options.push({ id: reference.id, value: reference.id, label: reference.name, iconUrl: reference.iconUrl }),
);
}
return options;
}
const Control = ({ children, ...props }: ControlProps<IconSelectOption, boolean, GroupBase<IconSelectOption>>) => (
<components.Control {...props}>
{( (selectedValue && selectedValue.iconUrl)) && (
<img
src={selectedValue?.iconUrl}
style={{ width: "24px", paddingLeft: "8px" }} />
)}
{children}
</components.Control>
);
return (
<>
{creatingItem === true && <ItemCreateModal show={creatingItem} moduleIdx={field.referencedModuleIdx} onCreateItem={onCreateItem} value={input} />}
<Controller
name={"inputfield-" + field.index}
key={"inputfield-" + field.index}
defaultValue={selectedValue}
rules={{ required: field.required }}
render={renderProps => {
return (
<CreatableSelect
className="react-select-container"
classNamePrefix="react-select"
options={options}
isClearable
isSearchable
placeholder="..."
isDisabled={field.readOnly}
components={{ Option: IconOption, Control }}
{...register("inputfield-" + field.index)}
{...renderProps.field}
onCreateOption={(value) => handleCreateOption(value)}
onChange={e => {
setSelectedValue(e as IconSelectOption);
renderProps.field.onChange(e);
}}
/>
);
}}
/>
</>
)
}
本文标签: javascriptCreateable Select trying to add and item and make it selectedStack Overflow
版权声明:本文标题:javascript - Createable Select; trying to add and item and make it selected - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744782234a2624783.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论