Concatenated get requests API call in react - reactjs

This get request - http://localhost:7000/api/search/gender/Female results in
{
"id": 32,
"email": "no"
},
Backend code:
const app = require('express').Router(),
db = require('../../../config/db'),
User = require('../../../config/User')
app.get('/search/:type/:value', async (req, res) => {
const { type, value } = req.params
module.exports = app

What you want is to set up your back end to read query string params and use those params to do your db filtering so you can make a single request to get whatever filtered data you need
Then your url would look something like:
/api/search?email=true&gender=female&city=athens
or whatever combination of params you need at the time
You should be able to pass objects to axios and it will serialze the front end params for you or use the URL API and specifically it's searchParams to construct url's

Related

How to create an api dynamic route in Next.js?

I am trying to add a dynamic route to the api folder for GET request.
In this scenario it works fine
api/[product]
const baseUrl ='https://myUrl'
const { product } = req.query
const url = `${baseUrl}/${product}`
And then testing http://localhost:3000/api/phone in Postman returns the correct result. So far it is fine.
Then, instead of fetching the api by product, I want my dynamic property to be filter values. Filter syntax provided by particular api looks like this ?$filter=name eq 'Milk'.
Filtering on frontend works fine when I test it in postman or in browser.
https://myUrl/phone?$filter=name eq 'iphone'
Now I try to do exactly the same as above, now in api folder. But it returns 404 This page could not be found..
api/[productType]
const baseUrl ='https://myUrl/phone?$filter'
const { productType } = req.query
const url = `${baseUrl}=${productType}`
In Postman I test it so:
`http://localhost:3000/api/phone=name-eq-'iphone'`
And get 404 response.
How to fix this issue? Any help will be appreciated.
I have created a demo at https://github.com/vercel-support/so-71663454-nextjs-route-poc with
// /api/[productType]
export default function handler (req, res) {
const baseUrl ='https://myUrl/phone?$filter'
const { productType } = req.query
const url = `${baseUrl}=${productType}`
res.json({ productType, query: req.query, url })
}
If you visit the link using https://so-71663454-nextjs-route-poc.vercel-support.app/api/phone=name-eq-'iphone'
You should be able to see the following result:
{
"productType": "phone=name-eq-'iphone'",
"query": {
"productType": "phone=name-eq-'iphone'"
},
"url": "https://myUrl/phone?$filter=phone=name-eq-'iphone'"
}

Redirect an array of URLs in Express JS

I want to assign an array of URLs from a React app (using Express server side rendering) and assign 301 redirects to each URL.
The slug/id format is changing and I need a way to ensure old links already indexed by Google our saved in the wild have a way to find their way to the new URL format.
This function will be a one-time use, as new URLs will follow the new slug/id format, but the redirects need to remain so that they can continue their redirects.
I know how to assign a single redirect to one URL using res.redirect but not an entire array.
(This is my first SO post. Tried to explain this as well as I can but apologies if there are gaps).
You can use a loop to create router.get functions, so something like:
const urls = ['/url1', '/url2', '/url3'];
urls.forEach(url => {
router.get(url, (req, res, next) => {
res.redirect(301, '/redirected-route');
})
)};
If they all need to go to different URLs rather than all to the same one, then you can define the redirect array as an array of objects with oldUrl, and newUrl properties to create a more dynamic redirect.
const urls = [
{ oldUrl: '/url1', newUrl: '/new-url1' },
{ oldUrl: '/url2', newUrl: '/new-url2' },
{ oldUrl: '/url3', newUrl: '/new-url3' }
];
urls.forEach(url => {
router.get(url.oldUrl, (req, res, next) => {
res.redirect(301, url.newUrl);
})
)};

How can I post form data from react to an express.js server and use it as part of a url string

Just to make this clearer. I have a form where the user inputs a name which is passed to the apiUrl const to become part of the URL string. The form input data is passed through state as {this.state.input}. After the user inputs the form with the name he wants to search for, he clicks a button which calls the onButtonSubmit function that fetches the data with the updated apiUrl parameters. The catch is, this is running on the front-end and as this is a proprietary api, I don't want to expose the api key (which is part of the url) to the user.
I have set up an express.js server but I'm still unsure on how I can post the form data to it and then use that in the same manner used in my code below.
onButtonSubmit = () => {
const apiUrl = 'URLStringPart1' + this.state.input + 'URLStringpart2withAPIKey';
fetch(apiUrl)
.then(res => res.json())
.then(
result => {
this.setState({
isLoaded: true,
array1: result.array1,
array2: result.array2,
array3: result.array3,
array4: result.array4,
array5: result.array5,
route: 'fetched'
});
},
error => {
this.setState({
isLoaded: false,
error: error
});
}
);
}
So the output I'm looking for would follow something like this:
Post form data from frontend after the user submits it with a
button click
Through the backend, after the form data is posted, use it to update the apiurl and then fetch the data from the api(using axios perhaps)
Send the fetched data back to the frontend
I think you need to use prams, in your express server the API route should look like this: api/users/:name --> returns user with this name.
Then try fetching this API by sending the request to the server like this:
http://locahost:8000/api/users/${this.state.name}

How do I forward a cookie using fetch in getServerSideProps?

I'm using Nextjs for my app. On a page, I would like to fetch data from an authenticated API endpoint ('/api/profile').
I have tried the following, with no success:
export async function getServerSideProps(ctx) {
const { req, res } = ctx
const cookies = cookie.parse(req.headers.cookie ?? '')
const mycookie = cookies[MY_COOKIE] // mycookie exists and is set correctly
if (mycookie) {
const response = await fetch(process.env.SERVER_HOST+'/api/profile', {
credentials: 'same-origin' // I tried with and without this, also tried "include" instead
})
...
I have 2 questions:
Is there a way to avoid having to enter the absolute URL? (I was hoping to simply use '/api/profile', since it's an "internal" api)
How do I make sure the cookie required to fetch data from /api/profile is forwarded through fetch?
N.B: My cookie is httpOnly.
Turns out I'm allowed to manually forward the cookie through:
if (mycookie) {
const response = await fetch(process.env.SERVER_HOST+'/api/profile', {
headers: {
cookie: mycookie
}
})
...
if you use get server side props then the recommended way is to process whatever data fetching functions you have directly in getserversideprops.
calling fetch /api is redundant. what you can do is to extract the function from the api and use it directly in getserversideprops.
what you are doing now is
client -> serverside rendering -> api -> serverside rendering -> client
it can become
client -> serverside rendering -client

Pass array from React client to MongoDB

I have a get route on my server-side that responds with two random records from MongoDB. I currently have a couple records hard-wired as excluded records that will never be returned to the client.
app.get("/api/matchups/:excludedrecords", (req, res) => {
const ObjectId = mongoose.Types.ObjectId;
Restaurant.aggregate([
{
$match: {
_id: { $nin: [ObjectId("5b6b5188ed2749054c277f95"), ObjectId("50mb5fie7v2749054c277f36")] }
}
},
{ $sample: { size: 2 } }
]).
This works, but I don't want to hard-wire the excluded records, I want to dynamically pass the ObjectIds from the client side. I want the user to be able to exclude multiple records from the random query. I have an action creator that pushes the ObjectId the user wishes to exclude through a reducer so that it becomes part of the store, and the store is an array that includes all the ObjectIds of the records the user wishes to exclude. Here's my action that fetches the random records, taking the excluded records from the store as an argument:
export function fetchRecords(excludedrecords) {
const excludedarray = JSON.stringify(excludedrecords); // Don't currently have this, but feel like I need to.
const request =
axios.get(`http://localhost:3000/api/matchups/${excludedarray}`);
return {
type: "FETCH_MATCHUP_DATA",
payload: request
};
}
I have the sense I need to stringify the array on the client side and parse it on the server side, but I'm not sure how. I've started something like:
app.get("/api/matchups/:excludedrecords", (req, res) => {
const excludedRecords = JSON.parse(req.params.excludedrecords);
const ObjectId = mongoose.Types.ObjectId;
Restaurant.aggregate([
{
$match: {
_id: { $nin: [excludedRecords] } //
}
},
But how do I get ObjectId() to wrap around each record number that is passed in params? I've tried inserting the number on the client side into a template string, like ObjectId('${excludedrecord}'), which results in me passing an array that looks like what I want, but when it gets stringified and parsed it doesn't quite work out.
Sorry if this question is a bit messy.
First of all you should pass the array of string as a body of the http request and not as a part of the url. You do not pass an array parameter as part of the url or in the query string.
Second, you must transcode the to $nin: [ObjectId(excludedRecord1), ObjectId(excludedRecord2)]
at the server side.
Hope it helps!

Resources