Student here, trying to create an app for my thesis, using Laravel, React and Inertia.
I am trying to create a simple, reusable Combobox component. It needs to have an id HTML attribute and it needs to contain an id as a value, so that I can use both in a Laravel controller.
This is what I’ve got. Problem is that most of the lines of the handleSelect function don’t work. (Marked with "does not happen".)
When the user selects an item from the ul, I expect:
- the visible input {title}_input to contain item.name -> doesn’t happen
- the hidden {title}_id to contain item.id -> doesn’t happen
- the ul to close -> DOES happen
const {useState} = React;
const Combobox = ({}) => {
const [input, setInput] = useState('')
const [returnValue, setReturnValue] = useState ('')
const [showUl, setShowUl] = useState(false)
//TURN INTO PROPS
const title = 'test'
const array = [
{ id: 1, name: 'eins' },
{ id: 2, name: 'zwei' },
{ id: 3, name: 'polizei' },
]
//end of props
const filteredArray = (
input
? array.filter(item => item.name.toLowerCase().includes(input.toLowerCase()))
: array
)
const handleSelect = (name, id) => {
setInput(name) // does not happen.
setReturnValue(id) // does not happen.
setShowUl(false)
console.log(`input is now ${input}`) // does not happen.
}
return (
<div>
<input
id={`${title}_input`}
type="text"
placeholder='choose an option'
value={input}
onChange={e => {setInput(e.target.value)}}
onFocus={() => {setShowUl(true)}}
onBlur={() => {setShowUl(false)}}
/>
<input
id={`${title}_id`}
type="hidden"
value={returnValue}
/>
{showUl &&
<ul>
{filteredArray.map(item => (
<li
key={item.id}
onClick={() => handleSelect(item.name, item.id)}
>{item.name}</li>
))}
</ul>
}
</div>
)
}
ReactDOM.createRoot(
document.getElementById("root")
).render(
<Combobox/>
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
2
Answers
Try this
or
The function isn’t being called. So it’s really all of the lines of code in that function, and it’s not that they "don’t work" but rather that they’re simply not being invoked in the first place.
This event is occurring first:
Which is effectively re-rendering the component before that
click
event is ever processed. Remove it and theclick
event works as expected:To hide the menu is a bit more involved than just an
onBlur
event for the<input>
element. A tool like this one may be what you’re looking for, or perhaps creating your own. But essentially you’d want to hide the<ul>
when clicking anywhere except the<input>
or the<ul>
.