Project 49 of 100 – Search with Autocomplete

Hey! I’m on a mission to make 100 React.js projects ending March 31st. Please follow my dev.to profile or my twitter for updates and feel free to reach out if you have questions. Thanks for your support!

Link to the deployed project: Link
Link to the …


This content originally appeared on DEV Community and was authored by James Hubert

Hey! I'm on a mission to make 100 React.js projects ending March 31st. Please follow my dev.to profile or my twitter for updates and feel free to reach out if you have questions. Thanks for your support!

Link to the deployed project: Link
Link to the repo: github

Today I wanted to create an autocomplete component in React because I haven't implemented search in React before much less autocomplete. I'm actually curious how other people implement this from scratch because with the Star Wars API it's fairly easy. They have their own search feature that returns an array of JSON results and the number of Star Wars characters any search is going to return is necessarily small. What if your database has 100,000 possible results? I suppose you could put a numeric limit on the results in most databases.

For the basic search component I adapted this Dev.to blog post into a functional component. Rather than use their API, I decided to use a Star Wars character search API that is open and doesn't require a signup that exposes my email.

The structure of the website is simple. It uses an App component and a Search component, where the important logic happens. It uses three pieces of state- query, searchResults and selectedCharacter which are all set to empty at initialization:

  const [query,setQuery] = useState('');
  const [searchResults,setSearchResults] = useState([]);
  const [selectedCharacter,setSelectedCharacter] = useState(null);
Enter fullscreen mode Exit fullscreen mode

In the return statement we create a form with a text input for the search feature:

return (
    <form className='search-form-container'>
      <input 
        placeholder='Search for...'
        onChange={handleInputChange}
        value={query}
      />
    </form>
  )
Enter fullscreen mode Exit fullscreen mode

As the user searches we initiate the API call to the Star Wars API using their search URL query:

const searchURL = 'https://swapi.dev/api/people/?search=';

const getInfo = () => {
    console.log('Getting info from API...')
    fetch(searchURL+query)
      .then(res => res.json())
      .then(data => setSearchResults(data.results))
      .catch(e => {
        console.log({error: e});
    });
}

const handleInputChange = (e) => {
    setQuery(e.target.value)
    if (query && query.length > 0) {
      getInfo();
    }
}
Enter fullscreen mode Exit fullscreen mode

If results are returned from the API, we populate a ul element beneath the search box with results. I usually use the standard map method and create a key prop for the returned JSX children but I wanted to implement this a new way- with the React.Children.toArray() method. This way, you don't have to create your own key prop.

const results = React.Children.toArray(
    searchResults.map((item,idx) => (
      <li className='result-item' id={idx} onClick={handleQueryResultClick}>{item.name}</li>
    ))
)
Enter fullscreen mode Exit fullscreen mode

That looks like the following:

Alt Text

If the user selects one of these li elements, the index of that element from the original array of results stored in searchResults will match up with the id of the li element.

const handleQueryResultClick = (e) => {
    const searchResultId = e.target.id;
    setSelectedCharacter(searchResults[searchResultId]);
    setQuery([]);
}
Enter fullscreen mode Exit fullscreen mode

We then populate select data from that character's search into a div below the search box and clear the query state to remove the ul element of search results. I did this with a ternary.

<div>
        {selectedCharacter ? (
          <div className='character-display-container'>
            <p><span className='character-info-title'>name:</span> {selectedCharacter.name}</p>
            <p><span className='character-info-title'>height:</span> {selectedCharacter.height}</p>
            <p><span className='character-info-title'>mass:</span> {selectedCharacter.mass}</p>
          </div>
        ) : (
          <p className='no-results-prompt'>There are no results. Try typing something into the search bar above.</p>
        )}
</div>
Enter fullscreen mode Exit fullscreen mode

That's it! It was easier than I expected, largely because the API is so easy to use. I highly encourage you to try it.


This content originally appeared on DEV Community and was authored by James Hubert


Print Share Comment Cite Upload Translate Updates
APA

James Hubert | Sciencx (2021-02-21T06:20:38+00:00) Project 49 of 100 – Search with Autocomplete. Retrieved from https://www.scien.cx/2021/02/21/project-49-of-100-search-with-autocomplete/

MLA
" » Project 49 of 100 – Search with Autocomplete." James Hubert | Sciencx - Sunday February 21, 2021, https://www.scien.cx/2021/02/21/project-49-of-100-search-with-autocomplete/
HARVARD
James Hubert | Sciencx Sunday February 21, 2021 » Project 49 of 100 – Search with Autocomplete., viewed ,<https://www.scien.cx/2021/02/21/project-49-of-100-search-with-autocomplete/>
VANCOUVER
James Hubert | Sciencx - » Project 49 of 100 – Search with Autocomplete. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/02/21/project-49-of-100-search-with-autocomplete/
CHICAGO
" » Project 49 of 100 – Search with Autocomplete." James Hubert | Sciencx - Accessed . https://www.scien.cx/2021/02/21/project-49-of-100-search-with-autocomplete/
IEEE
" » Project 49 of 100 – Search with Autocomplete." James Hubert | Sciencx [Online]. Available: https://www.scien.cx/2021/02/21/project-49-of-100-search-with-autocomplete/. [Accessed: ]
rf:citation
» Project 49 of 100 – Search with Autocomplete | James Hubert | Sciencx | https://www.scien.cx/2021/02/21/project-49-of-100-search-with-autocomplete/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.