Search code examples
reactjsaxiosbing-api

How do I pass the api key with query into this get request in react using axios for bing web search api


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

Solution

  • 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;