Passing Multiple parameters as catch them - node.js

I'm trying to pass 'slug' in the URL by adding 'id' and 'type'.
Code:
`/${category.slug}?cid=${category._id}&type=${category.type}`
<Route path="/:slug" element={<ProductListPage />} />
URL
http://localhost:3000/Samsung-3whQlbAYpm?cid=61ed050cab3efd275d49efd6&type=store
Problem : However, in the useParam() I received only slug not addition parameters such as 'cid' and 'type'
For example,
let params = useParams();
Its params have only 'slug' value which is 'Samsung-3whQlbAYpm'
How can I get addition value ?

The useParams hook only gets you the defined route params from the path part of the URL. If you want to access the queryString then use the useSearchParams hook from react-router-dom.
const [searchParams] = useSearchParams();
const cid = searchParams.get("cid");
const type = searchParams.get("type");
If you happen to still be using react-router-dom v5 then use the location object to get the search string to be passed to a URLSearchParams constructor.
const { search } = useLocation();
const searchParams = new URLSearchParams(search);

Related

Using JSON.stringify on [object Object] gives "[object Object]" on React

I am trying to pass an object data from one page to another.
I have a line of code that can pass id and I tried to use it to pass object rather than an integer id but I can't get it right.
The code for passing id from source page:
const navigate = useNavigate();
id && navigate(generatePath("/employeelistedit/:id", { id })); //sample code which works fine when used
The code for passing the object data from source page copying the format of the code above:
function sourcePage(){
const navigate = useNavigate();
var values = {id: "someData", startd: "someData", endd: "someData"}
values && navigate(generatePath("/harvestcalendarmonitoring/:values", { values }));
    } //with useNavigate and generatePath
This is the code in another page which receives the data:
const { values } = useParams(); //values gives [object Object]
const x = JSON.stringify(JSON.stringify(values)) //gives "[object Object]"
const y = Object.prototype.toString.call(values) //gives [object String]
For my routing, this is how I wrote it:
<Route path="/harvestcalendarmonitoring/:values" element={< Harvestcalendarmonitoring />} /> //refers to the receiving page
I know I'm not doing it right cause I know that "[object Object]" is showing that something is wrong somewhere in my codes.
Any help and suggestions would be really much appreciated. Thank you in advance.
It looks like you missed the stringify step:
function sourcePage(){
const navigate = useNavigate();
var values = JSON.stringify({id: "someData", startd: "someData", endd: "someData"});
values && navigate(generatePath("/harvestcalendarmonitoring/:values", { values }));
} //with useNavigate and generatePath
However, make sure generatePath is also URL encoding this string values or else you will likely have an invalid URL.
When it comes time to parsing the string back into an object, be sure to call JSON.parse
With the help of Steve through his comment above/below this comment,
use JSON.stringify() for the object before passing and receive it using JSON.parse().
Code in source page:
values = JSON.stringify(values);
values && navigate(generatePath("/harvestcalendarmonitoring/:values", { values }));
Code in receiving page:
const {values} = useParams();
const w = JSON.parse(values) //the w variable gives the desired and/or expected object data

Extract Public Id From Cloudinary URL

I am using Cloudinary to host my media on the cloud for my NodeJS project.
To delete an image from the Clodinary Cloud, I need to pass a Public Id for that image, to the Cloudinary API.
I realised, Public ID is embedded into the url, how to I extract it out from the URL?
Because, I don't want to store my data in this format :
image : {
url : `http://res.cloudinary.com/cloud_name/image/upload/v1647610701/rsorl4rtziefw46fllvh.png`,
publicId : `rsorl4rtziefw46fllvh`
}
Rather, I find it better to store it like this :
image : `http://res.cloudinary.com/cloud_name/image/upload/v1647610701/rsorl4rtziefw46fllvh.png`
The solution to this problem is to implement a funciton which extracts the publicId for every URL passed in as argument.
Here's the function :
const getPublicId = (imageURL) => imageURL.split("/").pop().split(".")[0];
Edited after #loic-vdb 's suggestion
Explanation :
It splits the string in an array using "/" as seperator.
imageURL="http://res.cloudinary.com/cloud_name/image/upload/v1647610701/rsorl4rtziefw46fllvh.png";
becomes,
imageURL = [ 'http:',
'',
'res.cloudinary.com',
'cloud_name',
'image',
'upload',
'v1647610701',
'rsorl4rtziefw46fllvh.png' ]
Next, pop the array (returns the last element of the array)
imageURL = 'rsorl4rtziefw46fllvh.png';
Now, split this string into array using "." as seperator, we get :
imageURL = [ 'rsorl4rtziefw46fllvh', 'png' ]
Finally select the 0th element that is our PublicId return that
imageURL = 'rsorl4rtziefw46fllvh';
Based on the answer by a Cloudinary support team member
... the public_id contains all folders and the last part of the public_id is the filename.
Here is what I tried and worked
const path = require("path");
const getPublicId = (imageURL) => {
const [, publicIdWithExtensionName] = imageURL.split("upload/");
const extensionName = path.extname(publicIdWithExtensionName)
const publicId = publicIdWithExtensionName.replace(extensionName, "")
return publicId
};
especially for cases where you store your assets in folders

Having trouble grabbing data from MongoDB and using in new var (Next.js project)

Error I'm getting is this:
TypeError: Cannot read property 'latitude' of undefined
Here's the piece that's messing me up
const [user] = useCurrentUser();
var location = [user.latitude, user.longitude];
useCurrentUser() is here:
export function useCurrentUser() {
const { data, mutate } = useSWR('/api/user', fetcher);
const user = data?.user;
return [user, { mutate }];
}
I'm assuming I'm just calling it early, because it hasn't had a chance to go through the useCurrentUser() function yet. However, I can't for the life of me figure out how to call it when that's done?
edit:
It's also not usable later on in a component:
This works:
<span className="bold">{user ? user.latitude : ''}</span>
This doesn't:
<Map location={[user.longitude, user.latitude]}/>
What am I not understanding, hahaha

ES6 : Object restructuration for mailchimp api

I want to construct a object base on an array and another object.
The goal is to send to mailchimp api my users interests, for that, I've got :
//Array of skills for one user
const skillsUser1 = ["SKILL1", "SKILL3"]
//List of all my skills match to mailchimp interest group
const skillsMailchimpId = {
'SKILL1': 'list_id_1',
'SKILL2': 'list_id_2',
'SKILL3': 'list_id_3',
}
//Mapping of user skill to all skills
const outputSkills = skillsUser1.map((skill) => skillsMailchimpId[skill]);
console.log(outputSkills);
The problem is after, outputSkill get me an array :
["ID1", "ID3"]
But what the mailchimp api need, and so what I need : :
{ "list_id_1": true,
"list_id_2": false, //or empty
"list_id_3" : true
}
A simple way would be this (see comments in code for explanation):
// Array of skills for one user
const skillsUser1 = ["SKILL1", "SKILL3"]
// List of all my skills match to mailchimp interest group
const skillsMailchimpId = {
'SKILL1': 'list_id_1',
'SKILL2': 'list_id_2',
'SKILL3': 'list_id_3',
}
// Create an output object
const outputSkills = {};
// Use `Object.entries` to transform `skillsMailchimpId` to array
Object.entries(skillsMailchimpId)
// Use `.forEach` to add properties to `outputSkills`
.forEach(keyValuePair => {
const [key, val] = keyValuePair;
outputSkills[val] = skillsUser1.includes(key);
});
console.log(outputSkills);
The basic idea is to loop over skillsMailchimpId instead of skillsUser.
But that is not very dynamic. For your production code, you probably want to refactor it to be more flexible.
// Array of skills for one user
const skillsUser1 = ["SKILL1", "SKILL3"]
// List of all my skills match to mailchimp interest group
const skillsMailchimpId = {
'SKILL1': 'list_id_1',
'SKILL2': 'list_id_2',
'SKILL3': 'list_id_3',
}
// Use `Object.entries` to transform `skillsMailchimpId` to array
const skillsMailchimpIdEntries = Object.entries(skillsMailchimpId);
const parseUserSkills = userSkills => {
// Create an output object
const outputSkills = {};
// Use `.forEach` to add properties to `outputSkills`
skillsMailchimpIdEntries.forEach(([key, val]) => {
outputSkills[val] = userSkills.includes(key);
});
return outputSkills;
}
// Now you can use the function with any user
console.log(parseUserSkills(skillsUser1));

Passing path parameters in axios

I am using Axios with NodeJs and trying to pass path parameters in axios.get() method. For example, if URL is url = '/fetch/{date}', I want to replace {date} with the actual date while calling axios.get(url).
I went through the source code on Github and StackOverflow, but couldn't find any method.
Is it possible to keep URLs with parameters as a placeholder and replace them while actually calling the get method of Axios?
Axios doesn't have this feature and it looks like the team don't want to add it.
With credit to previous responders for inspiration, to me this seems like the solution closest to what you (and me) are looking for:
1 - Where you want to store all your URLs and their parameters, define them as functions which use a template string to return the composed URL:
export var fetchDateUrl = (date) => `/fetch/${date}`;
If you need any type-specific formatting of the value being concatenated into the URL, this function is a good place to do it.
2 - Where you want to make the request, call the function with the correct parameters:
import { fetchDateUrl } from 'my-urls';
axios.get(fetchDateUrl(someDateVariable))...;
Another variation, if you really like the idea of naming the parameters at the call site, you can define the URL function to destructure an object like this:
var fetchDateUrl = ({date}) => `/fetch/${date}`;
which you'd then use like this:
axios.get(fetchDateUrl({date: someDateVariable}));
Use template strings
url = `/fetch/${date}`
Or just tag it on
url = '/fetch/'+ date
I think using axios interceptors is better to do this :
//create your instance
const instanceAxios = axios.create({
baseUrl: 'http://localhost:3001'
]);
instanceAxios.interceptors.request.use(config => {
if (!config.url) {
return config;
}
const currentUrl = new URL(config.url, config.baseURL);
// parse pathName to implement variables
Object.entries(config.urlParams || {}).forEach(([
k,
v,
]) => {
currentUrl.pathname = currentUrl.pathname.replace(`:${k}`, encodeURIComponent(v));
});
const authPart = currentUrl.username && currentUrl.password ? `${currentUrl.username}:${currentUrl.password}` : '';
return {
...config,
baseURL: `${currentUrl.protocol}//${authPart}${currentUrl.host}`,
url: currentUrl.pathname,
};
});
// use like :
instanceAxios.get('/issues/:uuid', {
urlParams : {
uuid: '123456789'
}
})
For typescript users, you will need to add this, in one of your .d.ts
declare module 'axios' {
interface AxiosRequestConfig {
urlParams?: Record<string, string>;
}
}
( this is a POC, not really tested, doesn't hesitate if you see something wrong )
You can use template strings ie:
let sellerId = 317737
function getSellerAnalyticsTotals() {
return axios.get(`http://localhost:8000/api/v1/seller/${sellerId}/analytics`);
}
Given some API /fetch/${date} you likely want to wrap your axios call in a function.
const fetchData = (date) => axios.get(`/fetch/${date}`);
fetchData(dateObject.toFormat('yyyy-mm-dd'))
.then(result => { ... });
This requires the calling code to format date correctly however. You can avoid this by using a DateTime library that handles date string parsing and do the format enforcement in the function.
const fetchData = (date) => axios.get(`/fetch/${date.toFormat('yyyy-mm-dd')}`);
fetchData(dateObject)
.then(result => { ... });
you can do like this:
getProduct = (id) => axios.get(`product/${id}`);
I always do it like this:
const res = await axios.get('https://localhost:3000/get', { params: { myParam: 123 } });
I find this to be much clearer than template strings.
More explanation here

Resources