I can't figure it out how to pass params to an anonymous function in Nuxt 3.
index.vue:
<template>
<form #submit.prevent="signUpNewsletter()">
<input type="email" placeholder="example#x.com" v-model="userEmail">
<input type="submit" value="Submit">
</form>
</template>
<script setup>
const userEmail = ref('x#x.de')
function signUpNewsletter () {
useAsyncData(
'newsletter',
() => $fetch('/api/sign_up_news', {
method: 'POST', // Post method works
body: {
email: userEmail.value
}
})
)
}
</script>
server/api/sign_up_news.js:
import { createClient } from '#supabase/supabase-js'
export default async (email) => { // can't read the parameter
const SUPABASE_KEY = 'key123'
const SUPABASE_URL = 'url.supabase.co'
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const { data, error } = await supabase
.from('newsletter')
.insert([{ email }]) // <<< Fails!
return data
};
working:
import { createClient } from '#supabase/supabase-js'
export default async () => {
const SUPABASE_KEY = 'key123'
const SUPABASE_URL = 'url.supabase.co'
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const { data, error } = await supabase
.from('newsletter')
.insert([{ email: 'hi#it.works' }]) // <<< Works!
return data
};
Do you know how to pass parameter into Nuxt 3 server/api? Or do you got a source? The official docs are blank at this moment.
Update, I just found out today that useBody is now deprecated and it is replaced with readBody.
See this issue for reference.
I don't think you're able to pass params directly into the functions the way you're doing.
In another part of the docs, it says that when you pass a body into the server/api function, you'll need to retrieve it using await useBody(event).
Use useBody
Its mention in the docs: https://v3.nuxtjs.org/guide/features/server-routes#handling-requests-with-body
you just need to read through
import { createClient } from '#supabase/supabase-js'
export default async (event) => { // can't read the parameter
const body = await useBody(event)
const SUPABASE_KEY = 'key123'
const SUPABASE_URL = 'url.supabase.co'
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const { data, error } = await supabase
.from('newsletter')
.insert([{ email: body.email }])
return data
};
Related
I am using react-query in my TS project:
useOrderItemsForCardsInList.ts:
import { getToken } from '../../tokens/getToken';
import { basePath } from '../../config/basePath';
import { getTokenAuthHeaders } from '../../functions/sharedHeaders';
import { useQuery } from 'react-query';
async function getOrderItemsForCardsInList(listID: string) {
const token = await getToken();
const response = await fetch(`${basePath}/lists/${listID}/order_items/`, {
method: 'GET',
headers: getTokenAuthHeaders(token)
});
return response.json();
}
export default function useOrderItemsForCardsInList(listID: string) {
if (listID != null) {
return useQuery(['list', listID], () => {
return getOrderItemsForCardsInList(listID);
});
}
}
I use my query result over here:
import { useCardsForList } from '../../hooks/Cards/useCardsForList';
import useOrderItemsForCardsInList from '../../hooks/Lists/useOrderItemsForCardsInList';
import usePaginateCardsInList from '../../hooks/Cards/usePaginateCardsInList';
export default function CardsListFetch({ listID }: { listID: string }) {
const { isLoading, isError, error, data } = useCardsForList(listID);
const { orderItems } = useOrderItemsForCardsInList(listID);
const pagesArray = usePaginateCardsInList(orderItems, data);
return (
...
);
}
However, on my const { orderItems } = useOrderItemsForCardsInList(listID); line, I get the following error:
Property 'orderItems' does not exist on type 'UseQueryResult<any, unknown> | undefined'.
How can I resolve this? I don't really know how to consume the result of my query on Typescript, any help is be appreciated
The property on useQuery that you need to consume where you find your data is called data, so it should be:
const { data } = useOrderItemsForCardsInList(listID);
if that data has a property called orderItems, you can access it from there.
However, two things I'm seeing in your code:
a conditional hook call of useQuery (which is forbidden in React)
your queryFn returns any because fetch is untyped, so even though you are using TypeScript, you won't get any typesafety that way.
If you are using React with react-query, I suggest you install this devDependency called: "#types/react-query". When using VS Code or any other smart text editor that will help, because it will help you with type suggestions.
npm i --save-dev #types/react-query
Then go to your code and fix couple things:
remove condition from useOrderItemsForCardsInList(). Don’t call React Hooks inside loops, conditions, or nested functions. See React hooks rules.
import UseCategoryResult and define interface for your return object. You can call it OrderItemsResult or similar. Add type OrderType with the fields of the order object or just use orderItems: any for now.
Add return type UseQueryResult<OrderItemsResult> to useOrderItemsForCardsInList() function.
Fix return value of getOrderItemsForCardsInList(), it should not be response.json() because that would be Promise, not actual data. Instead use await response.json().
So your function useOrderItemsForCardsInList() will return UseQueryResult which has properties like isLoading, error and data. In your second code snipper, you already use data in one place, so instead rename data to orderData and make sure you define default orderItems to empty array to avoid issues: data: orderData = {orderItems: []}
useOrderItemsForCardsInList.ts:
import { getToken } from '../../tokens/getToken';
import { basePath } from '../../config/basePath';
import { getTokenAuthHeaders } from '../../functions/sharedHeaders';
import { useQuery, UseCategoryResult } from 'react-query';
type OrderType = {
id: string;
name: string;
// whatever fields you have.
}
interface OrderItemsResult {
orderItems: OrderType[],
}
async function getOrderItemsForCardsInList(listID: string) {
const token = await getToken();
const response = await fetch(`${basePath}/lists/${listID}/order_items/`, {
method: 'GET',
headers: getTokenAuthHeaders(token)
});
const data = await response.json();
return data;
}
export default function useOrderItemsForCardsInList(listID: string): UseQueryResult<OrderItemsResult> {
return useQuery(['list', listID], () => {
return getOrderItemsForCardsInList(listID);
});
}
Use your query result:
import { useCardsForList } from '../../hooks/Cards/useCardsForList';
import useOrderItemsForCardsInList from '../../hooks/Lists/useOrderItemsForCardsInList';
import usePaginateCardsInList from '../../hooks/Cards/usePaginateCardsInList';
export default function CardsListFetch({ listID }: { listID: string }) {
const { isLoading, isError, error, data } = useCardsForList(listID);
const { data: orderData = { orderItems: []}} = useOrderItemsForCardsInList(listID);
const pagesArray = usePaginateCardsInList(orderItems, data);
return (
...
);
}
I am trying to display my date from GraphCMS in my blog application. I receive this error when I go to my single post link (http://localhost:3000/posts/union-types-and-sortable-relations)
"
page in load functions has been replaced by url and params
Error: page in load functions has been replaced by url and params
"
Here is my code
<script context='module'>
export const load = async ({fetch, page: {params}}) => {
const {slug} = params
const res = await fetch(`/posts/${slug}.json`)
if(res.ok) {
const {post} = await res.json()
return {
props: {post},
}
}
}
</script>
<script>
export let post
</script>
<svelte:head>
<title>Emrah's Blog | Welcome</title>
</svelte:head>
<pre>{JSON.stringify(post, null, 2)}</pre>
Can you please help. Thanks
Try using params instead of page: params, though the latter still works in Sveltekit 278 (which I'm using).
Besides, I'm curious to know what makes you prefer this method to querying GraphCMS for your single post. I do it like this:
import {client} from '$lib/js/graphql-client'
import {projectQuery} from '$lib/js/graphql-queries'
export const load = async ({ params }) => {
const {slug} = params
const variables = {slug}
const {project} = await client.request(projectQuery, variables)
return {
props: {
project
}
}
}
Yes, this has been changed a while ago, now the different parts of what used to be page are passed directly into the load function:
export async function load({ fetch, page }) {
const { params, url } = page
}
export async function load({ fetch, params, url }) {
}
Something else to consider is that now there are page endpoints, if your file is [slug].svelte you can make a file [slug].js and add the following:
export async function get({ params }) {
const { slug } = params;
const post = {}; // add the code to fetch from GraphCMS here
return {
status: 200,
body: {
post
}
}
}
With this you can remove the load function and make your code simpler (especially because you technically already have all this code in your /posts/[slug].json.js file.
<script context='module'>
export async function load({ fetch, params}){
let id = params.users
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
const user = await response.json()
if(response.ok){
return {props:{user}}
}
return {
status: response.status,
error : new Error(" sorry no user found")
}
}
export let user
I'm working with Next.js, I tried accessing data but got this error:
Error: Error serializing `.profileData` returned from `getStaticProps` in "/profile/[slug]".
Reason: `undefined` cannot be serialized as JSON. Please use `null` or omit this value.
My code:
import { getAllBusinessProfiles } from '../../lib/api';
const Profile = ({ allProfiles: { edges } }) => {
return (
<>
<Head>
<title>Profile</title>
</Head>
<Hero />
<section>
{edges.map(({ node }) => (
<div key={node.id}>
<Link href={`/profile/${node.slug}`}>
<a> {node.businessInfo.name} </a>
</Link>
</div>
))}
</section>
</>
);
}
export default Profile;
export async function getStaticProps() {
const allProfiles = await getAllBusinessProfiles();
return {
props: {
allProfiles
}
};
}
getAllBusinessProfiles from api.js:
const API_URL = process.env.WP_API_URL;
async function fetchAPI(query, { variables } = {}) {
const headers = { 'Content-Type': 'application/json' };
const res = await fetch(API_URL, {
method: 'POST',
headers,
body: JSON.stringify({ query, variables })
});
const json = await res.json();
if (json.errors) {
console.log(json.errors);
console.log('error details', query, variables);
throw new Error('Failed to fetch API');
}
return json.data;
}
export async function getAllBusinessProfiles() {
const data = await fetchAPI(
`
query AllProfiles {
businessProfiles(where: {orderby: {field: DATE, order: ASC}}) {
edges {
node {
date
title
slug
link
uri
businessInfo {
name
title
company
image {
mediaItemUrl
altText
}
highlight
phone
city
country
facebook
instagram
email
website
profiles {
profile
profileInfo
}
extendedProfile {
title
info
}
}
}
}
}
}
`
);
return data?.businessProfiles;
};
What could be the error here? I used the getStaticProps method on Next.js but got the error above instead. Please, check. Thanks.
The error:
Server Error
Error: Error serializing .profileData returned from getStaticProps in "/profile/[slug]".
Reason: undefined cannot be serialized as JSON. Please use null or omit this value.
I don't know what could cause this though.
Add JSON.stringify when calling an asynchronous function that returns an object.
Try modifying your getStaticProps function like this.
export async function getStaticProps() {
const profiles = await getAllBusinessProfiles();
const allProfiles = JSON.stringify(profiles)
return {
props: {
allProfiles
}
};
}
The JSON.stringify() method converts a JavaScript object or value to a JSON string, optionally replacing values if a replacer function is specified or optionally including only the specified properties if a replacer array is specified.
Source: MDN
I had this issue using Mongoose and Next.js.
To solve it: I switched from convert require to import then wrapped my result in JSON.parse(JSON.stringify(result));.
Good: import mongoose from 'mongoose';
Bad: const mongoose = require('mongoose');
I had the same serialization error when accessing a Vercel system environment variable in getStaticProps.
Using JSON.stringify did not do the trick, but String() worked. My code:
export async function getStaticProps() {
const deploymentURL = String(process.env.NEXT_PUBLIC_VERCEL_URL);
return {
props: {
deploymentURL,
},
};
}
Thanks to this GitHub issue for the inspiration
I had the same issue when I was working with redux with next js and the reason was one of the fields in the default state I set it to undefined. Instead I used null:
const INITIAL_STATE = {
products: [],
loading: false,
error: undefined,
cart: [],
};
error:undefined was causing the error. Because "undefined" cannot be serialized:
export async function getStaticProps() {
const allProfiles = await getAllBusinessProfiles();
return {
props: {
allProfiles
}
};
}
you are returning "allProfiles" which is the result of async getAllBusinessProfiles() which is either returning undefined, error or one of the fields of the returned object is undefined. "error" object is not serializable in javascript
Instead of using undefined, you have to use null as the value for your variables.
Note that the error shows you exactly which variable is using undefined as its value. Just modify its value to be null.
The value 'undefined' denotes that a variable has been declared, but hasn't been assigned any value. So, the value of the variable is 'undefined'. On the other hand, 'null' refers to a non-existent object, which basically means 'empty' or 'nothing'.
Source: [1]
I was having the same issue while trying to find a match in the array of data using the id. The issue I had was the items in the array had ids which were numbers while the value I was getting from params was a string. So all i did was convert the number id to a string to match the comparison.
export async function getStaticProps({ params }) {
const coffeeStore = coffeeStoreData.find(
(store) => store.id.toString() === params.slug[0]
);
return {
props: {
coffeeStore,
},
};
}
install a package called babel-plugin-superjson-next and superjson and added a .babelrc file with these contents:
{
"presets": ["next/babel"],
"plugins": ["superjson-next"]
}
see this topic : https://github.com/vercel/next.js/discussions/11498.
I had a similar problem too where I was fetching data through apollo directly inside of getStaticProps. All I had to do to fix the error was add the spread syntax to the return.
return {
props: {
data: { ...data }
}
}
return { props: { allProfiles: allProfiles || null } }
In getStaticProps() function, after fetching your data it will be in json format initially, but you should change it as follow:
const res = await fetch(`${APP_URL}/api/projects`);
const data = JSON.parse(res);
now it will work.
When you call api you should use try catch. It will resolve error.
Example:
import axios from "axios";
export const getStaticProps = async () => {
try {
const response = await axios.get("http:...");
const data = response.data;
return {
props: {
posts: data
}
}
} catch (error) {
console.log(error);
}
}
Hope help for you !
put res from API in Curly Brackets
const { res } = await axios.post("http://localhost:3000/api", {data})
return { props: { res } }
try this, it worked for me:
export async function getStaticProps() {
const APP_URL = process.env.PUBLIC_NEXT_WEB_APP_URL;
const res = await fetch(`${APP_URL}/api/projects`);
const projects = await res.json();
return {
props: {
projects: projects?.data,
},
};
}
I am trying to send data from front-end to back-end. Here is my front:
import axios from 'axios'
const api = axios.create({
baseURL: `${process.env.BASE_FRONT_URL}`, // process.env.BASE_FRONT_URL = http://localhost:8010
})
export const postTip = async (payload) => {
try {
const { data } = await api.post(`post-tip`, payload);
return data;
} catch (e) {
return [];
}
};
And here is back-end:
const router = require('express').Router();
const tipController = require('../controllers/tips/tipController')
router.post('post-tip', tipController.postTip);
That function tipController.postTip actually just receive and shows data, but when I trigger this end-point I get error: POST http://localhost:8010/undefined/post-tip 404 (Not Found). So, what's wrong with end-point and how can I make it work? Also, I have no idea, where does this undefined come from? Am I missing something?
I have found my mistake. Actually process.env.BASE_FRONT_URL was really undefined, so, I made it like that:
import axios from 'axios'
const api = axios.create({
baseURL: 'http://localhost:8084',
})
export const postTip = async (payload) => {
try {
const { data } = await api.post(`post-tip`, payload);
return data;
} catch (e) {
return [];
}
};
But the most important thing is that on back-end I have to use the same port (8084)
I am getting the error below, when I use getServerSideProps function to retrieve data from Binance API.
import binance from "../config/binance-config";
export async function getServerSideProps() {
const res = await binance.balance((error, balances) => {
console.info("BTC balance: ", balances.BTC.available);
});
return {
props: {
res,
},
};
}
import Binance from "node-binance-api"
const binance = new Binance().options({
APIKEY: 'xxx',
APISECRET: 'xxx'
});
export default binance;
Error output:
Error: Error serializing `.res` returned from `getServerSideProps` in "/dashboard".
Reason: `undefined` cannot be serialized as JSON. Please use `null` or omit this value.
I'm not sure how to resolve this error. I would just like to be able to mine (and display) the response by sending it as props in another component.
Thank you!
Here is how I solved it in NextJs
// Get Data from Database
export async function getServerSideProps(ctx) {
const { params } = ctx;
const { slug } = params;
await dbConnect.connect();
const member = await Member.findOne({ slug }).lean();
await dbConnect.disconnect();
return {
props: {
member: JSON.parse(JSON.stringify(member)), // <== here is a solution
},
};
}
Convert your data into json format when you are fetching it through an Api,
export async function getServerSideProps(context) {
const res = await fetch(`https://.../data`)
const data = await res.json()
if (!data) {
return {
redirect: {
destination: '/',
permanent: false,
},
}
}`enter code here`
return {
props: {}, // will be passed to the page component as props
}
}
You can read more detail on this link, https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering
put res from API in Curly Brackets
const { res } = await binance.balance((error, balances) => {
console.info("BTC balance: ", balances.BTC.available);
});
return {
props: {
res,
},
};
This is actually a simple error. The props that are being returned from getServerSideProps must be wrapped in curly brackets as shown below:
return {props: {res}}
This will clear the serialization error provided no nulls are being returned in response