2
\$\begingroup\$

I have a working code to have 2 search bars with dropdown suggestions, selectable by both mouse and arrow keys in TypeScript and Fresh/Preact. In there I have to explicitly declare individual hooks for different lists:

const list1 = ['rabbits', 'raccoons', 'reindeer', 'red pandas', 'rhinoceroses', 'river otters', 'rattlesnakes', 'roosters'] as const 
const list2 = ['jacaranda', 'jacarta', 'jack-o-lantern orange', 'jackpot', 'jade', 'jade green', 'jade rosin', 'jaffa'];
export default function SearchBar() {
 const [resultList1, setResultList1] = useState<null | (typeof list1[number])[]>(null);
 const [cursor1, setCursor1] = useState<Cursor>(0); 
 const [selectedItem1, setSelectedItem1] = useState<null | typeof list1[number]>(null); // State to track selected item for list 1
 
 const [resultList2, setResultList2] = useState<null | (typeof list2[number])[]>(null);
 const [cursor2, setCursor2] = useState<null | number>(0); // State to track selected item for list 2
 const [selectedItem2, setSelectedItem2] = useState<null | typeof list2[number]>(null); // State to track selected item for list 2
 
 /** activeList is used to determine whether the suggestion list should be popup or not */
 const [activeList, setActiveList] = useState<null | '1' | '2'>(null); // State to track active list

And explicitly return individual divs for different lists.

<div 
 id='search-div-1' 
 className="search-bar-container"
 >
 <input
 type="text"
 placeholder={'Search list 1'}
 onInput={(e) => {
 setResultList1(list1.filter(item => item.includes((e.target as HTMLTextAreaElement).value)));
 }}
 onFocus={() => setActiveList('1')}
 onKeyDown={(e) => handleKeyDown(e)}
 />
 <br />
 {resultList1 && activeList === '1' ? SuggestedList() : null}
 Cursor: {cursor1}<br />
 Selected item: <span id="Item 1">{selectedItem1}</span><br />
</div>
<div 
 id='search-div-2' 
 className="search-bar-container"
 >
 <input
 type="text"
 placeholder={'Search list 2'}
 onInput={(e) => {
 setResultList2(list2.filter(item => item.includes((e.target as HTMLTextAreaElement).value)));
 }}
 onFocus={() => setActiveList('2')}
 onKeyDown={(e) => handleKeyDown(e)}
 />
 <br />
 {resultList2 && activeList === '2' ? SuggestedList() : null}

Full code here.

I wonder if this is a good approach or not. My next step for this is to have the suggested lists disappear when they are unfocused by integrating it with Detect click outside multiple components.

toolic
14.3k5 gold badges29 silver badges200 bronze badges
asked Mar 29, 2024 at 11:12
\$\endgroup\$
1

1 Answer 1

1
\$\begingroup\$

You can refactor that component into a main component, and each list will have its own component. Then you can reuse the list component multiple times:

export default function SearchBarSplit() {
 /** Active list is used to determine whether the search list should be popup or not */
 const [activeList, setActiveList] = useState<ActiveList>(null); 
 return (
<>
 <SearchDiv listName="1" list={list1} activeList={activeList} setActiveList={setActiveList} />
 <SearchDiv listName="2" list={list2} activeList={activeList} setActiveList={setActiveList} />
 Active list: <strong>{activeList}</strong>
</>
 );
}
function SearchDiv({listName, list, activeList, setActiveList}: {listName: '1' | '2', list: List, activeList: ActiveList, setActiveList: StateUpdater<ActiveList>}){
 const [searchList, setSearchList] = useState<null | SearchList>(null);
 const [cursor, setCursor] = useState<Cursor>(0); 
 const [selectedItem, setSelectedItem] = useState<null | SelectedItem>(null); 
...

Full code.

Head over to Managing State – React to learn more many ways to manage states.

answered Mar 29, 2024 at 19:16
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.