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 -v
If 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-bar
Then select React > JavaScript.
- Install our packages:
npm install
npm install lucide-react
We 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 GoogleSearchBar;
Step 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 GoogleSearchBar;
Step 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 GoogleSearchBar;
Step 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 GoogleSearchBar;
Step 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 flex-col items-center min-h-screen bg-white p-4">
<form onSubmit={(e) => e.preventDefault()} className="w-full max-w-2xl mb-8">
<div className="relative">
<input
type="text"
value={searchTerm}
onChange={handleInputChange}
className="w-full px-5 py-3 pr-20 text-base bg-white border border-gray-200 rounded-full focus:outline-none focus:border-gray-300 shadow-md hover:shadow-lg transition-shadow duration-200"
placeholder="Search Google or type a URL"
/>
<div className="absolute right-0 top-0 mt-3 mr-4 flex items-center">
<button
type="button"
className="text-gray-400 hover:text-gray-600 mr-3"
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 bg-white rounded-lg shadow-md p-4">
<h2 className="text-xl font-bold mb-4">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 GoogleSearchBar;
Step 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 -p
You 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.js
file:
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
- Add Tailwind directives to your CSS:
In your
src/index.css
file, 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 App;
Step 9: Run Your Application
- Start your React application:
npm run dev
- Open your browser and navigate to
http://localhost:5173
to 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