#nextjs 14

1 messages · Page 1 of 1 (latest)

past jayBOT
#

Hi @eager kite. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Sure, I can provide you with some examples of Server Actions in Next.js based on the information I have.

Server Actions can be defined in two places: inside the component that uses it (Server Components only) or in a separate file (Client and Server Components), for reusability. You can define multiple Server Actions in a single file.

Here's an example of defining a Server Action inside a Server Component:

export default function ServerComponent() {
 async function myAction() {
 'use server'
 // ...
 }
}

Source (https://nextjs.org/docs/app/api-reference/functions/server-actions)

And here's an example of defining a Server Action in a separate file and then importing it into your Client Component:

// app/actions.js
'use server'
 
export async function myAction() {
 // ...
}

// app/client-component.jsx
'use client'
 
import { myAction } from './actions'
 
export default function ClientComponent() {
 return (
 <form action={myAction}>
 <button type="submit">Add to Cart</button>
 </form>
 )
}

Source (https://nextjs.org/docs/app/api-reference/functions/server-actions)

You can also handle errors from creating a new item in your Server Action:

// app/actions.ts
'use server'
 
export async function createTodo(prevState: any, formData: FormData) {
 try {
 await createItem(formData.get('todo'))
 return revalidatePath('/')
 } catch (e) {
 return { message: 'Failed to create' }
 }
}

Then, from a Client Component, you can read this value and display an error message:

#
// app/add-form.tsx
'use client'
 
import { useFormState, useFormStatus } from 'react-dom'
import { createTodo } from '@/app/actions'
 
const initialState = {
 message: null,
}
 
function SubmitButton() {
 const { pending } = useFormStatus()
 
 return (
 <button type="submit" aria-disabled={pending}>
 Add
 </button>
 )
}
 
export function AddForm() {
 const [state, formAction] = useFormState(createTodo, initialState)
 
 return (
 <form action={formAction}>
 <label htmlFor="todo">Enter Task</label>
 <input type="text" id="todo" name="todo" required />
 <SubmitButton />
 <p aria-live="polite" className="sr-only">
 {state?.message}
 </p>
 </form>
 )
}

Source (https://nextjs.org/docs/app/building-your-application/data-fetching/forms-and-mutations)

Please note that these examples are based on the information I have and may not be fully applicable to Next.js 14 if there are significant changes in that version.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@eager kite kapa.ai is still learning and improving, please let us know how it did by reacting below

eager kite
#

@past jay how to validate input in a server-action

past jayBOT
#

Let me check the knowledge base for you. One moment! :books:

#

Sure, you can validate input in a Server Action using a schema validation library like zod. Here's an example from the Next.js documentation:

import { z } from 'zod'
 
const schema = z.object({
 // Define your schema here...
})
 
export default async function submit(formData: FormData) {
 const parsed = schema.parse({
 id: formData.get('id'),
 })
 // ...
}

In this example, zod is used to define a schema for the form data. The parse method is then used to validate the form data against the schema. If the form data does not match the schema, an error will be thrown.

Source (https://nextjs.org/docs/app/building-your-application/data-fetching/forms-and-mutations)

Additionally, a user on GitHub shared a pattern for validation in Server Actions:

export function withValidation<S extends AnyObjectSchema>(
  schema: S,
  action: (data: InferType<S>) => unknown
) {
  return async (data: InferType<S>) => {
    const valid = await schema.validate(data);
    return action(data);
  };
}

In this example, the withValidation function takes a schema and an action. It returns a new function that validates the data against the schema before calling the action.

Source (https://github.com/vercel/next.js/issues/49344)

Please note that these examples are based on the information I have and may not be fully applicable to your specific use case.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@eager kite kapa.ai is still learning and improving, please let us know how it did by reacting below

eager kite
#

@past jay best way to use fetch in nextjs

past jayBOT
#

Let me check the knowledge base for you. One moment! :books:

#

Next.js extends the native fetch Web API to allow you to configure the caching and revalidating behavior for each fetch request on the server. You can use fetch with async/await in Server Components, in Route Handlers, and in Server Actions.

Here's an example of how to use fetch in Next.js:

async function getData() {
 const res = await fetch('<https://api.example.com/...'>)
 // The return value is *not* serialized
 // You can return Date, Map, Set, etc.
 
 if (!res.ok) {
 // This will activate the closest `error.js` Error Boundary
 throw new Error('Failed to fetch data')
 }
 
 return res.json()
}
 
export default async function Page() {
 const data = await getData()
 
 return <main></main>
}

Source (https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating)

Next.js also provides a way to set caching semantics for each request:

export default async function Page() {
 // This request should be cached until manually invalidated.
 // Similar to `getStaticProps`.
 // `force-cache` is the default and can be omitted.
 const staticData = await fetch(`<https://...`,> { cache: 'force-cache' })
 
 // This request should be refetched on every request.
 // Similar to `getServerSideProps`.
 const dynamicData = await fetch(`<https://...`,> { cache: 'no-store' })
 
 // This request should be cached with a lifetime of 10 seconds.
 // Similar to `getStaticProps` with the `revalidate` option.
 const revalidatedData = await fetch(`<https://...`,> {
 next: { revalidate: 10 },
 })
 
 return <div>...</div>
}

Source (https://nextjs.org/docs/app/api-reference/functions/fetch)

#

Remember, the fetch function in Next.js automatically dedupes fetch requests and provides a flexible way to fetch, cache, and revalidate data at the component level. This means all the benefits of Static Site Generation (SSG), Server-Side Rendering (SSR), and Incremental Static Regeneration (ISR) are now available through one API.

Source (https://nextjs.org/blog/next-13#data-fetching)

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@eager kite kapa.ai is still learning and improving, please let us know how it did by reacting below

eager kite
#

@past jay im having an error SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON

const handleFormSubmit = async (data: UserFormType) => {
'use server';

if (data?.username) {
  const response = await createUser(data);

  console.log(response);
}

};

'use server';

import UserFormType from '@customTypes/user';

async function createUser(data: UserFormType) {
try {
const res = await fetch(${process.env.NEXTAUTH_URL}/api/users, {
method: 'POST',
headers: {
'api-secret': ${process.env.NEXT_PUBLIC_API_SECRET},
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
cache: 'no-store',
},
body: JSON.stringify(data),
});

const result = await res.json();

return 'result';

} catch (error) {
return error;
}
}

export default createUser;

import bcrypt from 'bcrypt';
import dbConnect from 'src/lib/mongodb/mongoose';

// models
import Users from '@models/user.model';

// middleware
import validateApiKey from '@middlewares/validateApi';

export async function GET(request: Request) {
await dbConnect();

const apiKeyValidationResult = validateApiKey();

if (apiKeyValidationResult !== null) {
return apiKeyValidationResult;
}

try {
const result = await Users.find();

return Response.json({ data: result }, { status: 200 });

} catch (error) {
return Response.json({ message: error: ${error} }, { status: 500 });
}
}

export async function POST(request: Request) {

const body = await request.json();

console.log(body);

return Response.json({ message: 'yeah' }, { status: 200 });
}`

past jayBOT
#

Let me check the knowledge base for you. One moment! :books:

#

The error message SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON typically occurs when you're expecting a JSON response from a fetch request, but the server is returning HTML instead. This can happen if the server encounters an error and returns an HTML error page, or if the endpoint you're trying to reach doesn't exist and the server returns a 404 page.

In your case, the error might be occurring when you're trying to fetch data from ${process.env.NEXTAUTH_URL}/api/users.

Here's how you can handle this:

  1. Check the URL you're trying to fetch from. Make sure it's correct and that the server is set up to return JSON from this endpoint.

  2. Check the server logs for any errors. If the server is encountering an error and returning an HTML error page, the logs should give you more information about what's going wrong.

  3. Add error handling to your fetch request to handle non-OK responses. This can help you debug the issue and give you more information about what's going wrong. Here's an example:

const res = await fetch(`${process.env.NEXTAUTH_URL}/api/users`, {
  method: 'POST',
  headers: {
    'api-secret': `${process.env.NEXT_PUBLIC_API_SECRET}`,
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': '*',
    cache: 'no-store',
  },
  body: JSON.stringify(data),
});

if (!res.ok) {
  const text = await res.text();
  throw new Error(`Fetch failed: ${res.status} ${res.statusText}\n${text}`);
}

const result = await res.json();

In this example, if the response is not OK (i.e., the status is not in the range 200-299), we read the response body as text and throw an error. This can help you see what the server is returning when it's not returning JSON.

#

Please note that these are general debugging tips based on the information you provided and the error message you're seeing. The exact solution might depend on the specifics of your server setup and the endpoint you're trying to reach.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@eager kite kapa.ai is still learning and improving, please let us know how it did by reacting below

eager kite
#

@past jay
import CreateUser from '@modules/settings/templates/create-user';

import { getServerSession } from 'next-auth';
import { authOptions } from '@nextauth';

type PayloadProps = {
name: string;
id: string;
};

async function CreateUserPage() {
const session = await getServerSession(authOptions);

const newPayload = {
name: session?.name,
id: session?.id,
};

return <CreateUser userInfo={newPayload} />;
}

export default CreateUserPage;

Property 'name' does not exist on type 'Session'.
Property 'id' does not exist on type 'Session'.

past jayBOT
#

Let me check the knowledge base for you. One moment! :books:

#

The error message Property 'name' does not exist on type 'Session'. Property 'id' does not exist on type 'Session'. is indicating that the Session object returned by getServerSession does not have name and id properties.

The Session object typically contains the following properties: user, expires, accessToken, sessionToken, user?.id, user?.name, user?.email, etc. The exact properties can vary depending on your authentication provider and the session data you're storing.

If you're trying to access the user's name and id, you should access them through the user property of the Session object. Here's how you can do it:

async function CreateUserPage() {
  const session = await getServerSession(authOptions);

  const newPayload = {
    name: session?.user?.name,
    id: session?.user?.id,
  };

  return <CreateUser userInfo={newPayload} />;
}

In this example, session?.user?.name and session?.user?.id are used to access the user's name and id. The ?. operator is used to avoid a TypeError if session or user is undefined.

Please note that these are general tips based on the information you provided and the typical structure of a Session object in NextAuth.js. The exact solution might depend on the specifics of your authentication setup and the session data you're storing.

Source (https://nextjs.org/docs/pages/building-your-application/routing/authenticating#authenticating-server-rendered-pages)

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: