I am trying to make a custom select box component with parent and shild components, with autocomplete and also fetching from api. The problem is that i am trying to fire onchange
function from parent to child to select an item from the select box but it is not working, can someone tell me where is the problem?
export function SelectComponent() {
const [results, setResults] = useState([]);
const [selectedValue, setSelectedValue] = useState<ComboBoxOption>();
const handleOnChange = (e: any) => {
if (!e.target.value.trim()) return setResults([]);
const filteredValue = results.filter((item: any) =>
item.value.toString().toLowerCase().startsWith(item.toLowerCase())
);
setResults(filteredValue);
};
useEffect(() => {
const fetchData = async () => {
const response = await axios.get(...);
setResults(response.data);
};
fetchData();
}, []);
return (
<div>
<SelectField
options={results}
value={selectedValue?.value}
onChange={handleOnChange}
onSelect={item => setSelectedValue(item)}
/>
</div>
);
}
export function SelectField({
...
}: SelectFieldProps) {
const [isOpen, setIsOpen] = useState(false);
const [isActive, setIsActive] = useState(false);
const [defaultValue, setDefaultValue] = useState("");
const handleOnChange: React.ChangeEventHandler<HTMLInputElement> = event => {
setIsOpen(true);
setDefaultValue(event.target.value);
onChange && onChange(event);
};
return (
<div>
<input
placeholder={placeholder}
value={defaultValue}
onChange={handleOnChange}
/>
<button onClick={() => {setIsOpen(!isOpen);}}></button>
<ul>
{options.map((option: any, index: any) => {
return (
<li
key={index}
onClick={() => {setIsOpen(false);}
>
<span>{option.value}</span>
</li>
);
})}
</ul>
)
</div>
);
}
It looks like the problem may be in the handleOnChange
function in the SelectComponent
. The function is trying to filter the results
state based on the value
of the input element, but it should be filtering based on the e.target.value
instead. Also, it's using item.toLowerCase()
which doesn't make sense, instead it should use e.target.value.toLowerCase()
:
const handleOnChange = (e: any) => {
if (!e.target.value.trim()) return setResults([]);
const filteredValue = results.filter((item: any) =>
item.value.toString().toLowerCase().startsWith(e.target.value.toLowerCase())
);
setResults(filteredValue);
};
Also, in the SelectField
component, it seems that you are not calling the onSelect
prop when an option is selected. You should call the onSelect
prop and pass the selected option as a parameter when an option is clicked, like so:
<li
key={index}
onClick={() => {
setIsOpen(false);
onSelect(option);
}}
>
<span>{option.value}</span>
</li>
I would also recommend using onBlur
instead of onClick
for the input field, this way it can be closed when the user clicks outside of the component.