How can I resolve this? I put req.query parameter with an array but I can't destructure or use items from my array. I getting on my next.js API backend just [object Object] or undefined. How can I select what I want?
const fetchData = async (queryKey: any, manufacturer) => {
const res = await fetch(
`http://localhost:3000/api/data/get?&manufacturer=${manufacturers}`
);
return await res.json();
};
const manufacturers = [
{ name: 'Samsung', type: 'TV' },
{ name: 'Nokia', type: 'Phone' },
];
const { data, status } = useQuery(
['somekey', manufacturer],
({ queryKey }) => fetchData(queryKey, manufacturer)
);
And here is the next API where I can't get values from the query I getting just
[Object, Object] or undefined,
this code work if just put on the front end just a simple array or string without an object in variable manufacturers.
But how i can get values from [Object, object]?
I try it
const { name, type } = req.query.manufacturer
const { name, type } = req.query.manufacturer[0]
or select just one field dont work to = const some = req.query.manufacturer[0].name
export const handler = async (
req: NextApiRequest,
res: NextApiResponse<Data>
) => {
const { name, type } = req.query.manufacturer;
};
export default handler;
Could you try const [{ name, type }] = req.query.manufacturer? Seems to be what you need
edit
Also, you may want to try instead of http://localhost:3000/api/data/get?&manufacturer=${manufacturers} => http://localhost:3000/api/data/get?&manufacturer=${encodeURIComponent(JSON.stringify(manufacturers))}
It probably will be accessible with { name, type } = req.query.manufacturer then
Related
I want to apply server side search filter by text using redux toolkit.
I have two query builder methods in place. One for fetching all items and second for fetching only filtered data.
Query builder for fetching all items is
getAllBlogs: builder.query<BlogType[], void>({
queryFn: async () => {
const collectionRef = collection(Firestore, BLOG_COLLECTION)
const q = query(collectionRef, limit(1000))
const resp = await getDocs(q)
return {
data: resp.docs.map((doc) => doc.data() as BlogType),
}
},
providesTags: (result) => {
const tags: { type: 'Blogs'; id: string }[] = [
{ type: 'Blogs', id: 'LIST' },
]
if (result) {
result.forEach(({ id }) => {
tags.push({
type: 'Blogs',
id,
})
})
}
return tags
},
}),
This works fine and I'm getting the whole list through useGetAllBlogsQuery data.
Query builder for fetching filtered data is here: (Partially completed)
getBlogsByTitle: builder.query<BlogType[], string>({
queryFn: async (title) => {
const collectionRef = collection(Firestore, BLOG_COLLECTION)
const q = query(
collectionRef,
where('searchIndex', 'array-contains', title),
limit(1000),
)
const resp = await getDocs(q)
return {
data: resp.docs.map((doc) => doc.data() as BlogType), // Correct data
}
},
// I'm trying to only push the resultant items in state. This is not working
providesTags: (result) => {
const tags: { type: 'Blogs'; id: string }[] = []
if (result) {
result.forEach(({ id }) => {
tags.push({
type: 'Blogs',
id,
})
})
}
return tags
},
}),
I have react component looks like this where I'm calling these queries.
const Blogs: NextPage = () => {
const { data: blogs } = blogsApi.useGetAllBlogsQuery()
const [getBlogsByTitle] = blogsApi.useLazyGetBlogsByTitleQuery()
const debounced = useDebouncedCallback(async (value) => {
const { data } = await getBlogsByTitle(value)
console.log(data) // Correct data
}, 500)
return (
<div>
<InputText
onChange={(e) => debounced(e.target.value)}
/>
</div>
)}
The above code has two functionalities.
Fetch all the items on initial load.
Filter when debounced function is being called.
What I want is when getBlogsByTitle is called it will auto update the same state blogs in redux and we don't have to do much.
We are getting correct response in getBlogsByTitle but this query is not updating state with only its filtered response.
I'm new to redux-toolkit. Can someone help me out here where am I doing wrong ?
I have an api that requires some parameters to filter based on the the passed in parameter. It is similar top localhost:8000/api/v1/products?page=1&user=62831ebc8cecf3c829c4b2d9&category=62831ebc8cecf3c829c4b2d9
So I created a react action
export const listProducts =
(page = '', user = '', category = '') =>
async (dispatch) => {
try {
dispatch({ type: PRODUCT_LIST_REQUEST })
const { data } = await axios.get(
`${process.env.REACT_APP_API}/api/v1/products?&page=${page}&user=${user}&category=${category}`
)
dispatch({
type: PRODUCT_LIST_SUCCESS,
payload: data,
})
} catch (error) {
dispatch({
type: PRODUCT_LIST_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
})
}
}
The Idea is that when I when I dispatch dispatch(listProducts(1, user._id) and I leave the 3rd parameter empty, It returns Invalid category ''
How can I make the api ignore unsent paramaters and only use sent parameters.
I have tried replacing (page = '', user = '', category = '') with (page = null, user = null, category = null)
Now i get Invalid category null
EDIT: In some instances, i would want to pass only categories while in some other instances, I would want to pass user and page only. How can I do this ${process.env.REACT_APP_API}/api/v1/products?&page=${page}&user=${user}&category=${category} to only accept data in the object and ignore what's not available
If the number of parameters passed to the function is frequently changing, or if you don't have control on what will be passed to the function I would achieve this by using a single object as a parameter rather than multiple parameters.
Example:
Instead of export const listProducts = (page = '', user = '', category = '') => you can pass a single object and deconstruct the fields from the object like:
export const listProducts = ({page, user, category }) =>
//will be passed like:
listProducts({
page: 1,
user: data.user,
category: ''
})
Why?
You don't have to control the order of the parameters while passing arguments to the function and if a field is not passed to the function; it will evaluate to undefined:
const obj1 = {
page: 1,
user: 'test',
category: 'first'
}
const obj2 = {
page: 2,
user: 'test2'
}
const obj3 = {
user: 'test3'
}
const listProducts = ({page, user, category}) => {
const str = `Parameters:\n page: ${page}\nuser: ${user}\ncategory: ${category}`
console.log(str)
}
listProducts(obj1)
listProducts(obj2)
listProducts(obj3)
console.log("\n-------------DEFAULT VALUES------\n")
/* Default value example: */
const listProducts2 = ({page = 1, user = '', category = ''}) => {
const str = `Parameters:\n page: ${page}\nuser: ${user}\ncategory: ${category}`
console.log(str)
}
listProducts2(obj1)
listProducts2(obj2)
listProducts2(obj3)
Ignoring undefined parameters (may not be efficient, just a try):
let url = `${process.env.REACT_APP_API}/api/v1/products?`
if(user) url += `&user=${user}`
if(page) url += `&page=${page}`
if(category) url += `&category=${category}`
I'm trying to run two sequencitally graphQL requests, the first one give me data that I need into the second one parameters. And I don't know how to wait to the first.
My program is the following one:
I have the declaration of my GraphQL requests:
const [
addConfigurableProductToCart,
{ error: errorAddingSimpleProduct, loading: isAddSimpleLoading }
] = useMutation(ADD_CONFIGURABLE_MUTATION);
const [getDataParentSku, { error, loading, data }] = useLazyQuery(
GET_PARENT_SKU
);
And the main workflow are in this function.
const handleAddProductsToCart = useCallback(
async csvProducts => {
let tempSkuErrorList = [];
for (let i = 0; i < csvProducts.length; i++) {
const orParentSku = getDataVariable(csvProducts[i][0]);
const variables = {
cartId,
quantity: parseInt(csvProducts[i][1], 10),
sku: csvProducts[i][0],
parentSku: orParentSku.then(res => {
return res.products.items[0].orParentSku;
})
};
try {
await addConfigurableProductToCart({
variables
});
} catch {
tempSkuErrorList.push(csvProducts[i][0]);
}
}
},
[
addConfigurableProductToCart,
cartId,
]
);
getDataVariable() is the function who call the first query (useLazyQuery()). And its content is:
const getDataVariable = useCallback(
async sku => {
getDataParentSku({
variables: { sku: sku }
});
return await data;
},
[getDataParentSku, data]
);
The error that I have been finding all the time is that when I need the data, is undefined.
Another option was the idea of using this library https://www.npmjs.com/package/graphql-lodash, in order to merge the query into one, but is outdated.
Thanks a lot for your help.
I have trouble post with axios
my post body is :
{
"action": "createRoom",
"params": {
"name": "cloud-services",
"title":"test",
"max_users": 50,
"guest_login": true
}
}
And I use axios it like this :
async createClassInSkyRoom({ action = "createRoom", name, title, max_users, guest_login }) {
const result = await instance().post(Constants.URL_SKYROOM, { action, params: { name, title, max_users, guest_login } })
return result
}
and my instance is :
module.exports = () => {
const instance = axios.create({})
return instance
}
And I get the following error :
err: TypeError: Converting circular structure to JSON
--> starting at object with constructor 'ClientRequest'
| property 'socket' -> object with constructor 'TLSSocket'
--- property '_httpMessage' closes the circle
at JSON.stringify (<anonymous>)
at stringify (/home/firefly/Desktop/project/taha-m/node_modules/express/lib/response.js:1128:12)
at ServerResponse.json (/home/firefly/Desktop/project/taha-m/node_modules/express/lib/response.js:260:14)
at ResponseHandler.send (/home/firefly/Desktop/project/taha-m/app/Handler/ResponseHandler.js:9:26)
at ClassController.goToClassOnSkyRoom (/home/firefly/Desktop/project/taha-m/app/Class/class.controller.js:62:28)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
Have you tride to change
const result = await instance().post(Constants.URL_SKYROOM, { action, params: { name, title, max_users, guest_login } }) to
const result = await instance.post(Constants.URL_SKYROOM, { action, params: { name, title, max_users, guest_login } }).
I think you don't need to run instace directly
I found the right request. Thank you all
async createClassInSkyRoom({ action = "createRoom", name, title, max_users, guest_login }) {
const result = await instance().post(Constants.URL_SKYROOM, data:{ action, params: { name, title, max_users, guest_login }})
return result
}
When i do this, after first return i don't have user.uid value:
const functions = require(`firebase-functions`);
exports.createNewUser = functions.auth.user().onCreate((user: { uid: string; }) => {
const newUserWallet: UserWallet = new UserWallet(user.uid);
const rootUserWallet = admin.database().ref(`/Users/UserWallet/${user.uid}`); //user.uid have value
return rootUserWallet.set(newUserWallet).then(() => {
const newUserSettings: UserSettings = new UserSettings(user.uid);
const rootUserSettings = admin.database().ref(`/Users/UserSettings/${user.uid}`); //user.uid is empty
return rootUserSettings.set(newUserSettings);
})
})
I try send value like this:
.then((user.uid) => { or this: .then(user.uid => {, but i have error:
Argument of type 'string' is not assignable to parameter of type '((value: void) => void | PromiseLike<void>) | null | undefined'.ts(2345)
How can I sent this value there? It's Firebase Function triggered OnCreate new user. Write in TypeScript.
Not sure what you're trying to do with the { uid: string; } bit. I don't think that's the type of the user object.
In either case, why not put user.uid into a const and use it within your function from there? like this:
exports.createNewUser = functions.auth.user().onCreate(user => {
const uid = user.uid;
// replace all instances of 'user.uid' with just 'uid'?
})