SO I been learning NextJS API routes and NodeJS recently, While I do know how to create dynamic routes now, I have some issues with a few things -
This is my api/matches.js file.
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
export default async function handler(req, res) {
const response = await fetch(`https://exampleapi.com/?&token=# `)
const jsonData = await response.json();
res.status(200).json(jsonData);
}
Now, I have another dynamic route for this API which fetches the match by a match slug, So this file was called /api/matches/[...matchslug].js
export default async function handler(req, res) {
const page = req.query.matchslug
const response = await fetch(`https://examleapi.com/?search[slug]=${page}&token=# `)
const jsonData = await response.json();
While this dynamic route fetches the result of one so if I went matches/exampelmatch, I do get the results for the examplematch, However I'm looking to somehow implement it in a way that
matches/examplematch1/examplematch2
Returns the data from the examplematch1 & examplematch2.
I'm not sure if building something like is possible, But very interested.
Thank you for your time and patience.
In your /api/matches/[...matchslug].js example, the value of matchslug will always be an array.
Instead of passing the page variable directly into fetch, you can map over the values in the matchslug array and use Promise.all to request each resource.
It would look something like this (I haven't tested this):
export default async function handler(req, res) {
const promiseArray = req.query.matchslug.map(async (slug) => {
const response = await fetch(`https://examleapi.com/?search[slug]=${slug}&token=# `)
const jsonData = await response.json();
return jsonData
})
const result = await Promise.all(promiseArray)
res.status(200).json(result);
}
Related
I'm relatively new working with promises in JS. I got the API call to work on the initial homepage, but I'm having issues when I go to another page that is using the same API call.
In my api.js file I have the following:
const key = apiKey;
const commentsUrl = axios.get(`https://project-1-api.herokuapp.com/comments/?api_key=${key}`);
const showsUrl = axios.get(`https://project-1-api.herokuapp.com/showdates?api_key=${key}`);
async function getData() {
const allApis = [commentsUrl, showsUrl];
try {
const allData = await Promise.allSettled(allApis);
return allData;
} catch (error) {
console.error(error);
}
}
In my index.html
import { getData } from "./api.js";
let data = await getData(); //This works and gathers the data from the API.
In my shows.html
import { getData } from "./api.js";
let showsData = await getData(); //This does not and says that cannot access commentsUrl (api.js) before it is initialized. But it is?
If I comment out the code from "show", the API GET request works fine and the index page loads the API data correctly. Can anyone explain to me what's happening and why I would be getting the uninitialized error?
I also should note that if I split the API calls onto two seperate two js files (one for the index, one for the shows), the API calls works and displays the data as it is intended to.
On the homepage, the code is executing the 2 GET requests on page load/initialization of the JS code. When you navigate away from the homepage, presumably with some sort of client-side routing, the 2 GET requests no longer reference 2 Promises as they have already been executed.
You could instead move the GET requests into your function like:
const key = apiKey;
async function getData() {
try {
const commentsUrl = axios.get(`https://project-1- api.herokuapp.com/comments/?api_key=${key}`);
const showsUrl = axios.get(`https://project-1-api.herokuapp.com/showdates?api_key=${key}`);
const allApis = [commentsUrl, showsUrl];
const allData = await Promise.allSettled(allApis);
return allData;
} catch (error) {
console.error(error);
}
}
I am trying to call an async function but I am getting an error
getUsersList(db).then is not a function
this is my code
async function getUsersList(db) {
const userCol = collection(db, 'Users');
const userSnapshot = await getDocs(userCol);
const tempUserList = userSnapshot.docs.map(doc => doc.data());
return tempUserList;
}
function App() {
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
const auth = getAuth(app);
var currentUser = auth.currentUser;
if(currentUser != null){
getUsersList(db).then((value) => {
console.log(value);
});
I also tried using await getUsersList but got the following error
Unexpected reserved word 'await'
So what I assume you're trying to do here const userSnapshot = await getDocs(userCol); is fetch some data that is then going to be used in your react component to render something (Maybe there's a fetch request in getDocs ?)
There is no return in your react component (but that's not what's causing your issue).
As it is it won't work using await since App() isn't an async function BUT you can't make it an async function since this is a standard react component.
What do you want to happen whilst waiting for the data to be fetched (= whilst your promise is pending) ? If you're happy to display nothing, why not just remove await before getDocs() ?
For more on this topic :
React: async and await not working with fetch
React Hooks: how to wait for the data to be fetched before rendering
I have the following get request where I call a bunch of data and pass it through to my EJS view.
router.get('/currentrentals', ensureAuthenticated, async (req, res) => {
const companies = await Company.getCompanies();
const barges = await Barge.getBarges();
const parishes = await Parish.getParishes();
const states = await State.getStates();
const pickupdropoff = await PickupDropoff.getPickupDropoff();
var notifications = await Notification.getNotifications();
JSON.stringify(barges);
JSON.stringify(companies);
JSON.stringify(parishes);
JSON.stringify(states);
JSON.stringify(pickupdropoff);
JSON.stringify(notifications);
var notifications = await notifications.sort((a, b) => b.id - a.id).slice(0,3);
res.render('currentrentals', {
name: req.user.name, companies: companies, barges: barges, parishes: parishes, states: states, pickupdropoff : pickupdropoff, notifications : notifications
});
}
);
Two questions:
I have multiple get requests that requires the same information. Is there a way to make this data available across the entirety of my site, so I don't have to rewrite this for each get path?
Is there a more succinct way to write the existing code I have? Perhaps looping through them or something of the sort? Simply for learning purposes.
The code currently works as-is.
Thanks!
If the data is constant, you can try this:
let data = null;
async function getData() {
if (!data) {
data = {
companies: await Company.getCompanies(),
barges: await Barge.getBarges();
parishes: await Parish.getParishes(),
states: await State.getStates(),
pickupdropoff: await PickupDropoff.getPickupDropoff(),
notifications: (await Notification.getNotifications()).sort((a, b) => b.id - a.id).slice(0,3)
};
}
return data;
}
router.get('/currentrentals', ensureAuthenticated, async (req, res) => {
res.render('currentrentals', { name: req.user.name, ...(await getData()) });
}
);
// other routes
So i'm making a fetch request from react to express and the api url requires params but I want the last bit of the url to be dynamic. How would I send a param from react to the api url in express? Heres the code
react
const [dynamic, setDynamic] = useState("somevalue")
useEffect(() => {
async function fetchData() {
const response = await fetch("/web")
const data = await response.json()
console.log(data)
}
fetchData()
}, [dynamic])
express.js
app.get("/web", async (req, res) => {
const response = await fetch("https://alexa.com/api?Action=urlInfo&Url=")
const data = await response.json()
res.json(data)
})
Basically, I would like the dynamic state value to be injected into the end of the URL in express.
Something like
react
const [dynamic, setDynamic] = useState("somevalue")
async function fetchData() {
const response = await fetch("/web" + dynamic)
const data = await response.json()
console.log(data)
}
Then in express when the API is called the URL changes to
const response = await fetch("https://alexa.com/api?Action=urlInfo&Url=somevalue")
How can I go about achieving this?
You define the parameter on the route handler side, setting up a route that matches the desired pattern. For example:
app.get("/foo/bar/:myparam", async (req, res) => {
//... here's your handler code
})
Will match /foo/bar/baz, and req.params.myparam === "baz" inside the handler.
http://expressjs.com/en/guide/routing.html#route-parameters
Using query params is similar, but you want to check the values of the req.query object instead, like:
// client side (React code)
await fetch("/foo/bar?myparam=baz")
...
// In your express handler:
req.query.myparam === "baz"
Use Dynamic value in params of api call.
React code would look like this:
const [dynamic, setDynamic] = useState("somevalue")
useEffect(() => {
async function fetchData() {
const response = await fetch(`/web/${dynamic}`)
const data = await response.json()
console.log(data)
}
fetchData()
}, [dynamic])
In Express.Js code
define the parameter on the route handler side, and use that in fetch api call
app.get("/web/:value", async (req, res) => {
const {value} = req.params;
const response = await fetch(`https://alexa.com/api?Action=urlInfo&Url=${value}`)
const data = response.json()
res.json(data)
})
I'm having problems fetching data from my API and I get this error. I have attached the JSON format below as I believe it is an issue with my structure. When I use a different res URL with objects nested inside an array, it works. But for my data, it is not. Can anyone help me please?
"Index.getInitialProps()" should resolve to an object. But found undefined instead"
import Layout from '../comps/Layout';
import Link from 'next/link';
import fetch from 'isomorphic-unfetch';
const Index = props => (
<Layout>
//List of movies here
</Layout>
);
Index.getInitialProps = async function() {
const res = await fetch('https://www.what-song.com/api/recent-movies')
const data = await res.json()
console.log(`Data: ${data}`)
}
export default Index;
The getInitialProps method basically supposed to set your component initial props. But, in your case you are returning nothing.
So, change your code to
Index.getInitialProps = async function() {
const res = await fetch('https://www.what-song.com/api/recent-movies')
const data = await res.json()
console.log(`Data: ${data}`)
return { data }; // <-- set whatever key you want.
}
For your reference