WUI logo

Search

This allows you to search data from a remote API.

version

4.1.2

install

yarn add @welcome-ui/search

usage

import { Search } from '@welcome-ui/search'

About #

It is based on the downshift library.

Default #

function () {
const [value, setValue] = React.useState('')
const handleChange = (newValue) => {
setValue(newValue)
}
return (
<Search
name="movies"
renderItem={item =>
item && (
<div style={{ display: 'flex', alignItems: 'center' }}>
<Shape w="40px" h="40px" shape="circle" mr="sm">
<img src={item.Poster} />
</Shape>
{item.Title} ({item.Year})
</div>
)
}
placeholder="Search a movie"
itemToString={item => item && item.Title}
onChange={handleChange}
value={value}
search={async function asyncSearch(s) {
const response = await fetch(`https://www.omdbapi.com?apikey=41514363&s=${s}`)
const data = await response.json()
return data.Search
}}
/>
)
}

With option groups #

To use option groups, you must provide two additional props: groupsEnabled that allow nested options and renderGroupHeader that renders the header of a specific group

function () {
const [value, setValue] = React.useState('')
const handleChange = (newValue) => {
setValue(newValue)
}
return (
<Field label="Movies & Series">
<Search
name="movies_series"
renderItem={item =>
item && (
<div style={{ display: 'flex', alignItems: 'center' }}>
<Shape w="40px" h="40px" shape="circle" mr="sm">
<img src={item.Poster} />
</Shape>
{item.Title} ({item.Year})
</div>
)
}
placeholder="Search a movie or series"
itemToString={item => item && item.Title}
groupsEnabled
renderGroupHeader={({ label, options }) => (
<Box p="xxs">
<Box display="flex" justifyContent="space-between" alignItems="center">
<Text variant="body3" m="0">
{label}
</Text>
<Tag>{options.length}</Tag>
</Box>
{options.length === 0 && <Text variant="body4">No results found</Text>}
</Box>
)}
onChange={handleChange}
value={value}
search={async function asyncSearch(s) {
const response = await fetch(`https://www.omdbapi.com?apikey=41514363&s=${s}`)
const data = await response.json()
const searchResults = (data.Search || []).reduce(
(acc, item) => {
if (item.Type === 'movie') {
acc.movies.push(item)
} else {
acc.series.push(item)
}
return acc
},
{ movies: [], series: [] }
)
return [
{ label: 'Movies', options: searchResults.movies },
{ label: 'Series', options: searchResults.series },
]
}}
/>
</Field>
)
}

Properties #

There are several core props you must pass through:

An async function (async/await or Promises) that takes a search string and returns an array of results (items).

For example, given an API call to https://www.omdbapi.com?s=fish that returns a payload like this:

{
Search: [
{Title: "Big Fish", Year: "2003", imdbID: "tt0319061", Type: "movie",},
{Title: "A Fish Called Wanda", Year: "1988", imdbID: "tt0095159", Type: "movie",},
{Title: "Fish Tank", Year: "2009", imdbID: "tt1232776", Type: "movie",},
{Title: "Rumble Fish", Year: "1983", imdbID: "tt0086216", Type: "movie",},
{Title: "Cold Fish", Year: "2010", imdbID: "tt1632547", Type: "movie",},
],
totalResults: "895",
Response: "True"
}

We could pass the following prop to the Search component:

search={async function asyncSearch(query) {
const response = await fetch('https://www.omdbapi.com?apikey=' + YOUR_API_KEY + '&s=' + query)
const data = await response.json()
return data.Search
}}

To use option groups, you should return the results as follows:

[
{label: 'My first group label', options: [movie1, movie2]}
{label: 'My second group label', options: [serie1, serie2]}
]
renderItem #

A component that renders each of the results in the list e.g.

renderItem={item => <div>{item.Title} ({item.Year})</div>}
itemToString #

A function that converts a selected result to a string e.g.

itemToString={item => item && item.Title}
All properties #

The rest of the props are below:

NameType(s)DefaultRequired
groupsEnabled
Boolean
icon
ReactElement<any, string | JSXElementConstructor<any>>
itemToString
(item: unknown) => string
minChars
number
3
onChange
(item: unknown, event: { preventDefault: () => void; target: Record<string, unknown>; }) => void
renderGroupHeader
(result: OptionGroup) => ReactElement<any, string | JSXElementConstructor<any>>
renderItem
(item: unknown) => string | ReactElement<any, string | JSXElementConstructor<any>>
search
(query: string) => Promise<unknown>
throttle
number
500
value
unknown
size
"sm"
"md"
"lg"
lg
variant
"error"
"focused"
"info"
"success"
"warning"

Packages #

Dependencies #
Peer dependencies #

Previous

RadioTab