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'
- 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) 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
Top comments (0)