Create a simple Google search bar component with React π΅π»β
We'll create a Google-style search bar component in React in about 7 minutes.
Here's how the final result will look:
And here's a video walkthrough (featuring me):
Step 1: Set Up Your React Environment
- Ensure you have Node.js installed on your system.
node -vIf you don't have Node.js installed, download and install it: https://nodejs.org/en/download/
- Create a new React project using Vite:
npm create vite@latest google-search-bar
cd google-search-barThen select React > JavaScript.
- Install our packages:
npm install
npm install lucide-reactWe use the lucide-react package for icons.
Step 2: Create the GoogleSearchBar Component
Create a new file called GoogleSearchBar.jsx in your google-search-bar/src and add the following code:
import React from 'react'
import { Search, Mic } from 'lucide-react'
 
const GoogleSearchBar = () => {
  // Component code will go here
}
 
export default GoogleSearchBarStep 3: Add Sample Data
Update GoogleSearchBar.jsx to include our sample data:
import React from 'react'
import { Search, Mic } from 'lucide-react'
 
const sampleData = [
  {
    id: 1,
    title: 'React Official Documentation',
    url: 'https://reactjs.org/',
  },
  {
    id: 2,
    title: 'Mozilla Developer Network (MDN)',
    url: 'https://developer.mozilla.org/',
  },
  {
    id: 3,
    title: 'Stack Overflow',
    url: 'https://stackoverflow.com/',
  },
  {
    id: 4,
    title: 'GitHub',
    url: 'https://github.com/',
  },
  {
    id: 5,
    title: 'npm',
    url: 'https://www.npmjs.com/',
  },
]
 
const GoogleSearchBar = () => {
  // Component code will go here
}
 
export default GoogleSearchBarStep 4: Implement the Search State and Results
Update GoogleSearchBar.jsx to include state and the debounce function.
We use a debouncer to trigger the search after a short delay when the user stops typing, rather than on every keystroke.
import React, { useState, useCallback, useEffect } from 'react'
import { Search, Mic } from 'lucide-react'
 
const sampleData = [
  {
    id: 1,
    title: 'React Official Documentation',
    url: 'https://reactjs.org/',
  },
  {
    id: 2,
    title: 'Mozilla Developer Network (MDN)',
    url: 'https://developer.mozilla.org/',
  },
  {
    id: 3,
    title: 'Stack Overflow',
    url: 'https://stackoverflow.com/',
  },
  {
    id: 4,
    title: 'GitHub',
    url: 'https://github.com/',
  },
  {
    id: 5,
    title: 'npm',
    url: 'https://www.npmjs.com/',
  },
]
 
const GoogleSearchBar = () => {
  // Todo for you: Add the below code to the GoogleSearchBar component:
  const [searchTerm, setSearchTerm] = useState('')
  const [searchResults, setSearchResults] = useState([])
 
  const debounce = (func, delay) => {
    let timeoutId
    return (...args) => {
      clearTimeout(timeoutId)
      timeoutId = setTimeout(() => func(...args), delay)
    }
  }
 
  // More code will be added here
}
 
export default GoogleSearchBarStep 5: Create the Search Handler
Add the search handler to GoogleSearchBar.jsx :
import React, { useState, useCallback, useEffect } from 'react'
import { Search, Mic } from 'lucide-react'
 
const sampleData = [
  {
    id: 1,
    title: 'React Official Documentation',
    url: 'https://reactjs.org/',
  },
  {
    id: 2,
    title: 'Mozilla Developer Network (MDN)',
    url: 'https://developer.mozilla.org/',
  },
  {
    id: 3,
    title: 'Stack Overflow',
    url: 'https://stackoverflow.com/',
  },
  {
    id: 4,
    title: 'GitHub',
    url: 'https://github.com/',
  },
  {
    id: 5,
    title: 'npm',
    url: 'https://www.npmjs.com/',
  },
]
 
const GoogleSearchBar = () => {
  const [searchTerm, setSearchTerm] = useState('')
  const [searchResults, setSearchResults] = useState([])
 
  const debounce = (func, delay) => {
    let timeoutId
    return (...args) => {
      clearTimeout(timeoutId)
      timeoutId = setTimeout(() => func(...args), delay)
    }
  }
 
  // Todo for you: Add the below code to the GoogleSearchBar component:
  const handleSearch = useCallback(
    debounce((term) => {
      if (term.trim() === '') {
        setSearchResults([])
      } else {
        const results = sampleData.filter((item) =>
          item.title.toLowerCase().includes(term.toLowerCase()),
        )
        setSearchResults(results)
      }
    }, 300),
    [],
  )
 
  useEffect(() => {
    handleSearch(searchTerm)
  }, [searchTerm, handleSearch])
 
  const handleInputChange = (e) => {
    setSearchTerm(e.target.value)
  }
 
  // JSX will be added here
}
 
export default GoogleSearchBarStep 6: Build the Component JSX
Complete the GoogleSearchBar.jsx component by adding the JSX:
import React, { useState, useCallback, useEffect } from 'react'
import { Search, Mic } from 'lucide-react'
 
const sampleData = [
  {
    id: 1,
    title: 'React Official Documentation',
    url: 'https://reactjs.org/',
  },
  {
    id: 2,
    title: 'Mozilla Developer Network (MDN)',
    url: 'https://developer.mozilla.org/',
  },
  {
    id: 3,
    title: 'Stack Overflow',
    url: 'https://stackoverflow.com/',
  },
  {
    id: 4,
    title: 'GitHub',
    url: 'https://github.com/',
  },
  {
    id: 5,
    title: 'npm',
    url: 'https://www.npmjs.com/',
  },
]
 
const GoogleSearchBar = () => {
  const [searchTerm, setSearchTerm] = useState('')
  const [searchResults, setSearchResults] = useState([])
 
  const debounce = (func, delay) => {
    let timeoutId
    return (...args) => {
      clearTimeout(timeoutId)
      timeoutId = setTimeout(() => func(...args), delay)
    }
  }
 
  const handleSearch = useCallback(
    debounce((term) => {
      if (term.trim() === '') {
        setSearchResults([])
      } else {
        const results = sampleData.filter((item) =>
          item.title.toLowerCase().includes(term.toLowerCase()),
        )
        setSearchResults(results)
      }
    }, 300),
    [],
  )
 
  useEffect(() => {
    handleSearch(searchTerm)
  }, [searchTerm, handleSearch])
 
  const handleInputChange = (e) => {
    setSearchTerm(e.target.value)
  }
 
  // Todo for you: Add the below code to the GoogleSearchBar component:
  return (
    <div className="flex min-h-screen flex-col items-center bg-white p-4">
      <form
        onSubmit={(e) => e.preventDefault()}
        className="mb-8 w-full max-w-2xl"
      >
        <div className="relative">
          <input
            type="text"
            value={searchTerm}
            onChange={handleInputChange}
            className="w-full rounded-full border border-gray-200 bg-white px-5 py-3 pr-20 text-base shadow-md transition-shadow duration-200 hover:shadow-lg focus:border-gray-300 focus:outline-none"
            placeholder="Search Google or type a URL"
          />
          <div className="absolute right-0 top-0 mr-4 mt-3 flex items-center">
            <button
              type="button"
              className="mr-3 text-gray-400 hover:text-gray-600"
              onClick={() =>
                alert(
                  'Voice search is unsupported in this demo.\nTry implementing this feature yourself π',
                )
              }
            >
              <Mic size={20} />{' '}
            </button>{' '}
            <button type="submit" className="text-blue-500 hover:text-blue-600">
              <Search size={20} />{' '}
            </button>{' '}
          </div>{' '}
        </div>{' '}
      </form>{' '}
      {searchResults.length > 0 && (
        <div className="w-full max-w-2xl rounded-lg bg-white p-4 shadow-md">
          <h2 className="mb-4 text-xl font-bold"> Search Results: </h2>{' '}
          <ul>
            {' '}
            {searchResults.map((result) => (
              <li key={result.id} className="mb-2">
                <a
                  href={result.url}
                  className="text-blue-600 hover:underline"
                  target="_blank"
                  rel="noopener noreferrer"
                >
                  {' '}
                  {result.title}{' '}
                </a>{' '}
              </li>
            ))}{' '}
          </ul>{' '}
        </div>
      )}{' '}
    </div>
  )
}
 
export default GoogleSearchBarStep 7: Add Tailwind CSS for styling
- Install Tailwind CSS: In your google-search-bar directory, run:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -pYou should now have a tailwind.config.js file in your project root.
Note: Ensure that you're in the google-search-bar directory when you run these commands. Otherwise tailwind will be installed in the wrong directory, and it won't style your components.
- Configure your tailwind.config.js: Paste the following code into yourtailwind.config.jsfile:
module.exports = {
  content: ['./src/**/*.{js,jsx,ts,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
}- Add Tailwind directives to your CSS:
In your src/index.cssfile, replace the existing code with the following:
@tailwind base;
@tailwind components;
@tailwind utilities;Step 8: Use the Component
Update your App.jsx (in google-search-bar/src ) to use the GoogleSearchBar component. Paste the following code:
import React from 'react'
import GoogleSearchBar from './GoogleSearchBar'
 
function App() {
  return (
    <div className="App">
      <GoogleSearchBar />
    </div>
  )
}
 
export default AppStep 9: Run Your Application
- Start your React application:
npm run dev- Open your browser and navigate to http://localhost:5173to see your Google-style search bar in action!
Congratulations! You've created a Google-style search bar in React with sample data.
Next steps:
- Connect your search bar to a real API. It would be fun to connect this to the Bing search API directly, or your custom backend, perhaps using Django Ninja