Populating Select Input with data from an API using Nextjs and typescript
Tags: nextjs, nestjs, node, api
Published: 2024-06-04 18:16:28

After a series of nerve racking attempts and failures including combing through the entire internet I was finally able to achieve this feat. I shall share with you the function I currently use to populate select input using Nextjs from a Nest js api backend.

Working with asynchronous functions can be a real paid and some of the errors I encountered while attempting this included

- Property 'data' does not exist on type 'Promise<any>'
- Type {} is not assignable to type ReactNode
- And the biggest pain of them all....  “Invalid Hook Call” Error in React: Hooks Can Only Be Called Inside of a Function Component

After literally taking days to achieve such a menial task I finally stumble upon a response on StackOverflow by Alarid (Shoutout to [Alarid](https://stackoverflow.com/users/1379837/alarid)) that pointed me to the right direction.

This is a front end implementation only and am using the following libaries

- Nextjs
- Axios
- Nextui


Of course this is just a "proof of concept" can can be edited to fit the libraries you are using on your nextjs project. For example you could be using the default 'fetch' method to pull data from an api endpoint or any other  third party library like swr or tanstack

- To begin make sure the libraries are installed

- Create file "apiSelect" in the filepath "@/app/lib/apiSelect.tsx"

- Use the code below and edit according to your need.



```

import axios from "axios";
import { useState, useEffect } from "react";
import {Select, SelectItem} from "@nextui-org/react";

function apiSelect(url : string , lable: string, selected: string="") {
  const [options, setOptions] = useState<string[]>([]);

  useEffect(() => {
    async function fetchData() {
      // Fetch data
      
      const { data } = await axios.get(url);
      const results: any[] = []
      // Store results in the results array
      data.forEach((value: any) => {
        results.push({
          key: value.id,
          value: value.name,
        });
      });
      // Update the options state
      setOptions([
        ...results
      ])
    }

    // Trigger the fetch
    fetchData();
  }, []);



  return (

            <Select 
                label={lable}
                className="max-w-xs" 
            >
                {(options).map((option: any) => (
                <SelectItem key={option.key}>
                    {option.value}
                </SelectItem>
                ))}
            </Select>
  );
}

export default apiSelect;
```

Incase you need to use authentication tokens you can include the token variable as an argument and implement using axios as shown below

```
import axios from "axios";
import { useState, useEffect } from "react";
import {Select, SelectItem} from "@nextui-org/react";

function apiSelect(url : string , token : string, lable: string, selected: string="") {
  const [options, setOptions] = useState<string[]>([]);

  useEffect(() => {
    async function fetchData() {
      // Fetch data
      const config = {
        headers: { Authorization: `Bearer ${token}` }
     };
      const { data } = await axios.get(url, config);
      const results: any[] = []
      // Store results in the results array
      data.forEach((value: any) => {
        results.push({
          key: value.id,
          value: value.name,
        });
      });
      // Update the options state
      setOptions([
        ...results
      ])
    }

    // Trigger the fetch
    fetchData();
  }, []);



  return (

            <Select 
                label={lable}
                className="max-w-xs" 
            >
                {(options).map((option: any) => (
                <SelectItem key={option.key}>
                    {option.value}
                </SelectItem>
                ))}
            </Select>
  );


export default apiSelect;
```

- Import the function to page.tsx file so that you can call the function.

`import apiSelect from "@/app/lib/apiSelect";`

- Call the function

You use the example below to call the function
With Token
 ` {apiSelect(url, token, "Select a Role")}`

Without token

` {apiSelect(url, "Select a Role")}`
 

Hope this helps save you lots of hours trying to figure this out...

Peace