Katharina Schreiber
Katharina Schreiber

Reputation: 1371

Fetch Next.js API in a component

I am super new to Next.js and I am struggling with API routes, or to be exact, how to get data out of those. I have written my serverless function in /api/weather.js

export default async function handler(req, res) {
const city = req.query.city;
const getWeatherData = await fetch(
    `https://api.weatherapi.com/v1/search.json?key=${process.env.WEATHER_API_KEY}&q=${city}&days=5&aqi=no&alerts=no`
  );
  const data = await getWeatherData.json();
  res.status(200).json(data)
  console.log(city)
}

City is undefined, as I was hoping to search city through my input field in a component SearchBar.js. For now http://localhost:3000/api/cities just returns an empty array, cause, of course, I need a city name to get the city. However the city name should come from SearchBar.js. However I didn't come far there. I have a query, but this is not connected to my API whatsoever.

export const SearchBar = () => {

const [query, setQuery] = useState('')
    const onChange = (e) => {
      const {value} = e.target;
      setQuery(value)
      

      let matchingCities = []

      if(value.length > 3) {
        const test = fetch('/api/cities', {
          method: 'GET'
        }).then((response) => response.json())
        console.log(test)
        //test returns a promise pending
      }
    }

  return(
    <div className="sm:col-span-2">
      <label htmlFor="email" className="block text-sm font-medium text-gray-700">
        Search city
      </label>
      <div className="mt-1">
        <input
          onChange={onChange}
          id="city"
          name="city"
          type="text"
          value={query}
          autoComplete="city"
          className="py-3 px-4 block w-full shadow-sm focus:ring-blue-500 focus:border-blue-500 border-gray-300 rounded-md"
        />
      </div>
    </div>
  )
}

I know that might be way too complex, but maybe someone could at least describe the necessary steps, to connect those get this query work for a city inside my input.

Upvotes: 1

Views: 1185

Answers (1)

Alex A.
Alex A.

Reputation: 1005

Generally, the steps are:

  • Your search bar in the browser page sends the request with the city name to your own API endpoint on the server
  • Your API function takes the city name, and sends the request to the weather provider (with the secret key)
  • When it gets the response, it responds to the original request, forwarding the data
  • Your browser receives the response and does something useful with it

A couple things to fix:

  • name of the endpoint: you have /api/weather.js, so in the SearchBar you should call /api/weather, not /api/cities
  • your api expects the city parameter, so you need to pass it the value from the input: /api/weather?city=${value}
  • maybe use await instead of .then, makes it easier to read (but that's optional)

See the working example here (check the console for output): https://codesandbox.io/s/next-js-api-with-lewagon-autocomplete-xrb3l?file=/components/SearchBar.jsx

I used LeWagon's API instead of the weather sevice, it doesn't require a key :)

Upvotes: 1

Related Questions