I am trying to create a search bar with bing web api and having trouble figuring out how to pass the api key along with the search query into the get request using axios. Also how do I get the user input from the search bar into the get request. If someone could help out with a detailed answer I'd appreciate it very much!
https://learn.microsoft.com/en-us/bing/search-apis/bing-web-search/search-the-web
this is what I've tried:
import React, { useEffect, useState } from 'react';
import axios from 'axios';
// Search bar capabilities under development
const BASE_URL = 'https://api.bing.microsoft.com/v7.0/search'
const API_KEY = process.env.REACT_APP_SEARCH_KEY;
const useSearch = (searchTerm) => {
const [data, setData] = useState(null);
const headers = {
headers: {
'Ocp-Apim-Subscription-Key:': 'API_KEY'
}
}
const params = {
headers: {
'q': `${searchTerm}`,
'count': 10,
'mkt': 'en-us',
}
}
useEffect(() => {
const fetchData = async () => {
const response = axios.get(`${BASE_URL}`, headers=headers);
setData(response?.data);
};
fetchData();
}, [searchTerm])
return {
data,
};
};
export default useSearch;
this is what my nav file looks like:
import React from 'react'
import './NavBar.css'
import logo_dark from '../../assets/logo_light2.png'
import search_icon_light from '../../assets/search-w.png'
import search_icon_dark from '../../assets/search-b.png'
import toggle_light from '../../assets/night.png'
import toggle_dark from '../../assets/day.png'
function NavBar({theme, setTheme}) {
/* ternary clause to change theme between light and dark mode */
const toggle_mode = () => {
theme == 'light' ? setTheme('dark') : setTheme('light');
}
return (
<div className='navbar' >
<img src={theme == 'light' ? logo_light : logo_dark} alt='' className='logo' />
<ul className='nav-list'>
<li>SEARCH</li>
</ul>
<div className='search-box'>
<input className='search-bar' type='text' placeholder='Search'></input>
<img className='search-icon' src={theme == 'light' ? search_icon_light : search_icon_dark} alt='' />
</div>
<img onClick={() => {toggle_mode()}} src={theme == 'light' ? toggle_light : toggle_dark} alt='' className='toggle-icon'></img>
</div>
)
}
export default NavBar
In your useSearch
hook you need to do this. I added in comment codes explaining what I am doing and what I have changed
import React, { useEffect, useState } from "react";
import axios from "axios";
// Search bar capabilities under development
const BASE_URL = "https://api.bing.microsoft.com/v7.0/search";
const API_KEY = process.env.REACT_APP_SEARCH_KEY;
const apiAuthHeader = {
"Ocp-Apim-Subscription-Key:": API_KEY,
};
// added named hook params for better readability
const useSearch = ( {searchTerm} ) => {
const [data, setData] = useState(null);
// Just a suggestion for further improvements
// TODO: Debounce search
// TODO: Add loading state and error handling
useEffect(() => {
// Every time the search term changes
// it will create a new params object with a new
// search term
const searchParams = {
q: `${searchTerm}`,
count: 10,
mkt: "en-us",
};
const fetchData = async () => {
// supports options, so you can specify two options in your case,
// headers for auth and params for your search params
const response = axios.get(`${BASE_URL}`, {
headers: apiAuthHeader,
params: searchParams,
});
setData(response?.data);
};
// only call fetch data if the search term is not empty
if (searchTerm)
{
fetchData();
}
}, [searchTerm]);
return {
data,
};
};
I see you are not using your search hook anywhere, in your NavBar. Just remember you will have to add debouching as well not to spam the api with every key stroke. I suggest looking at debouching here, since debouching is not in the scope of the question. https://www.freecodecamp.org/news/debouncing-explained/
I did some minor modifications, and I am assuming data
is an array, so you will have to render your data whoever you see fit. Also remember to do a check if there is data, otherwise nothing will render on initial fetch.
import React, { useState } from "react";
import "./NavBar.css";
// import your hook
function NavBar({ theme, setTheme }) {
const [searchQuery, setSearchQuery] = useState("");
// search query state is passed down to the hook
const { data } = useSearch({ searchTerm: searchQuery });
/* ternary clause to change theme between light and dark mode */
const toggle_mode = () => {
theme == "light" ? setTheme("dark") : setTheme("light");
};
return (
<div className="navbar">
<img
src={theme == "light" ? logo_light : logo_dark}
alt=""
className="logo"
/>
<ul className="nav-list">
<li>SEARCH</li>
</ul>
<div className="search-box">
<input
onChange={(e) => setSearchQuery(e.target.value)}
className="search-bar"
type="text"
placeholder="Search"
/>
<img
className="search-icon"
src={theme == "light" ? search_icon_light : search_icon_dark}
alt=""
/>
</div>
<img
onClick={() => {
toggle_mode();
}}
src={theme == "light" ? toggle_light : toggle_dark}
alt=""
className="toggle-icon"
></img>
{data && <p>{data}</p>}
</div>
);
}
export default NavBar;