Rumah  >  Artikel  >  hujung hadapan web  >  React - Tindakan Pelayan

React - Tindakan Pelayan

WBOY
WBOYasal
2024-08-09 07:34:12949semak imbas

Tindakan bentuk tindak balas.

React telah memperkenalkan Actions borang baharu dan cangkuk berkaitan untuk meningkatkan bentuk asli dan menyelaraskan komunikasi pelanggan-pelayan. Ciri ini membolehkan pembangun mengendalikan penyerahan borang dengan lebih berkesan, meningkatkan pengalaman pengguna dan kebolehselenggaraan kod. Untuk penerokaan yang mendalam tentang Tindakan borang React, anda boleh merujuk siaran terperinci saya pada siaran saya tentang Tindakan Borang React.

Tindakan Pelayan

Dengan React 18, ciri Komponen Pelayan telah diperkenalkan. Komponen pelayan bukan Rendering Sisi Pelayan (SSR), Komponen Pelayan dilaksanakan secara eksklusif pada pelayan semasa masa jalan dan masa binaan. Komponen ini boleh mengakses sumber bahagian pelayan, seperti pangkalan data dan sistem fail, tetapi mereka tidak mampu melakukan tindakan pihak klien seperti pendengar acara atau cangkuk.

Prasyarat

Untuk menunjukkan keupayaan Komponen Pelayan dan Tindakan Pelayan, kami akan menggunakan Next.js dan Prisma.

Next.js ialah rangka kerja React untuk membina aplikasi web tindanan penuh. Anda menggunakan Komponen React untuk membina antara muka pengguna dan Next.js untuk ciri dan pengoptimuman tambahan. Di bawah hud, Next.js juga mengabstrak dan mengkonfigurasi alatan yang diperlukan secara automatik untuk React, seperti penggabungan, penyusunan dan banyak lagi. Ini membolehkan anda menumpukan pada membina aplikasi anda dan bukannya menghabiskan masa dengan konfigurasi. ketahui lebih lanjut

Prisma ialah ORM yang memudahkan akses dan operasi pangkalan data, membolehkan anda membuat pertanyaan dan memanipulasi data tanpa menulis SQL. Ketahui lebih lanjut

Persediaan Awal
Mulakan dengan mencipta aplikasi Next.js baharu:
benang buat contoh pelayan aplikasi seterusnya

Struktur folder awal anda akan kelihatan seperti ini:

React - Server Actions

Naik taraf kepada Keluaran Canary untuk mengakses ciri React 19, termasuk Tindakan Pelayan:

yarn add next@rc react@rc react-dom@rc

pasang Prisma

yarn add prisma

Konfigurasi Prisma
Cipta fail skema Prisma di src/lib/prisma/schema.prisma:

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = "file:./dev.db"
}

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  age Int
}

Untuk tujuan demonstrasi, kami menggunakan SQLite. Untuk pengeluaran, anda harus menggunakan pangkalan data yang lebih mantap.

Seterusnya, tambahkan fail klien Prisma di src/lib/prisma/prisma.ts

// ts-ignore 7017 is used to ignore the error that the global object is not
// defined in the global scope. This is because the global object is only
// defined in the global scope in Node.js and not in the browser.

import { PrismaClient } from '@prisma/client'

// PrismaClient is attached to the `global` object in development to prevent
// exhausting your database connection limit.
//
// Learn more:
// https://pris.ly/d/help/next-js-best-practices

const globalForPrisma = global as unknown as { prisma: PrismaClient }

export const prisma = globalForPrisma.prisma || new PrismaClient()

if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma

export default prisma

Konfigurasikan Prisma dalam package.json:

{
  //other settings
  "prisma": {
    "schema": "src/lib/prisma/schema.prisma",
    "seed": "ts-node src/lib/prisma/seed.ts"
  }
}

Dan kemas kini tetapan TypeScript dalam tsconfig.json:

{
  //Other settings here...

  "ts-node": {
    // these options are overrides used only by ts-node
    // same as the --compilerOptions flag and the 
    // TS_NODE_COMPILER_OPTIONS environment variable
    "compilerOptions": {
      "module": "commonjs"
    }
  }
}

Pasang ts-node secara global:

yarn global add ts-node

Membenihkan Data Awal
Tambahkan fail benih di src/lib/prisma/seed.ts untuk mengisi data awal:

import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function main() {
  await prisma.user.create({
    email: "anto@prisma.io",
    name: "Anto",
    age: 35,
  });
  await prisma.user.create({
    email: "vinish@prisma.io",
    name: "Vinish",
    age: 32,
  });
}
main()
  .then(async () => {
    await prisma.$disconnect();
  })
  .catch(async (e) => {
    console.error(e);
    await prisma.$disconnect();
    process.exit(1);
  });

Pasang klien Prisma

yarn add @prisma/client

Jalankan arahan migrasi:

yarn prisma migrate dev --name init

Jika data benih tidak ditunjukkan, tambahkannya secara manual:

yarn prisma db seed

Hebat! Memandangkan pemasangan sudah sedia, anda boleh mencipta fail tindakan yang menjalankan operasi pangkalan data.

Mencipta Tindakan Pelayan
Tindakan Pelayan ialah ciri berkuasa yang membolehkan interkomunikasi pelayan-pelanggan yang lancar. Mari buat fail untuk operasi pangkalan data di src/actions/user.ts:

"use server";
import prisma from '@/lib/prisma/prisma'
import { revalidatePath } from "next/cache";

// export type for user
export type User = {
  id: number;
  name: string | null;
  email: string;
  age: number;
};


export async function createUser(user: any) {
  const resp = await prisma.user.create({ data: user });
  console.log("server Response");
  revalidatePath("/");
  return resp;
}

export async function getUsers() {
  return await prisma.user.findMany();
}

export async function deleteUser(id: number) {
  await prisma.user.delete({
    where: {
      id: id,
    },
  });
  revalidatePath("/");
}

Melaksanakan Komponen Pelayan

Mari kita cipta komponen pelayan React untuk membaca dan memberikan data daripada pangkalan data. Cipta src/app/serverexample/page.tsx:

import UserList from "./Users";
import "./App.css"

export default async function ServerPage() {
  return (
    <div classname="app">
      <header classname="App-header">
        <userlist></userlist>
      </header>
    </div>
  );
}

Tambah beberapa penggayaan dalam src/app/serverexample/App.css

.App {
  text-align: center;
}

.App-logo {
  height: 40vmin;
  pointer-events: none;
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

input {
  color: #000;
}

.App-link {
  color: #61dafb;
}

Buat komponen untuk mengambil dan memaparkan senarai pengguna:
src/app/serverexample/UserList.tsx

import { getUsers } from "@/actions/user";
import { UserDetail } from "./UserDetail";

export default async function UserList() {
  //Api call to fetch User details
  const users = await getUsers();

  return (
    <div classname="grid grid-cols-3 gap-5">
      {users.length ? (
        users.map((user) => <userdetail user="{user}"></userdetail>)
      ) : (
        <div classname="col-span3 opacity-60 text-sm text-center">
          No User found
        </div>
      )}
    </div>
  );
}

src/app/serverexample/UserDetail.tsx

export function UserDetail({ user }) {
  return (
    <div classname="flex items-center gap-4 border border-gray-600 py-1 px-4">
      <img classname="w-10 h-10 rounded-full" src="https://api.dicebear.com/9.x/personas/svg?seed=Shadow" alt="React - Tindakan Pelayan">
      <div classname="font-medium text-base dark:text-white">
        <div>{user.name}</div>
        <div classname="text-sm text-gray-500 dark:text-gray-400">
          {user.email}
        </div>
      </div>
    </div>
  );
}

Jalankan pelayan pembangunan:

yarn dev

Navigasi ke http://localhost:3000/servereexample untuk melihat senarai pengguna yang diberikan:
React - Server Actions

Secara lalai, komponen dalam Next.js ialah komponen pelayan melainkan anda menentukan arahan "guna klien". Perhatikan dua perkara penting:

  1. Definisi Komponen Async: Komponen pelayan boleh menjadi tak segerak kerana ia tidak dipaparkan semula dan hanya dijana sekali.
  2. Pengambilan Data: Pengguna baris const = menunggu getUsers(); mengambil data daripada pelayan dan memaparkannya pada masa jalan.

Meneroka Tindakan Pelayan

Tindakan Pelayan membolehkan interkomunikasi pelanggan-pelayan yang lancar. Mari tambahkan borang untuk mencipta pengguna baharu.

Buat fail baharu di src/app/serverexample/AddUser.tsx:

"use client";

import "./app.css";
import { useActionState } from "react";
import { createUser } from "../../actions/user";

const initialState = {
  error: undefined,
};

export default function AddUser() {
  const submitHandler = async (_previousState: object, formData: FormData) => {
    try {
      // This is the Server Action method that transfers the control 
      // Back to the server to do DB operations and get back the result.
      const response = await createUser({
        name: formData.get("name") as string,
        email: formData.get("email") as string,
        age: parseInt(formData.get("age") as string),
      });
      return { response };
    } catch (error) {
      return { error };
    }
  };
  const [state, submitAction, isPending] = useActionState(
    submitHandler,
    initialState
  );

  return (
    <div classname="mt-10">
      <h4 classname="text-center">Add new User</h4>{" "}
      <form action="%7BsubmitAction%7D" classname="text-base">
        <div classname="mt-6 text-right">
          Name:{" "}
          <input classname="ml-2" required name="name" type="text" placeholder="Name">
        </div>
        <div classname="mt-6 text-right">
          Email:{" "}
          <input classname="ml-2" name="email" type="email" placeholder="Email">
        </div>
        <div classname="mt-6 text-right">
          Age:{" "}
          <input classname="ml-2" name="age" type="text" placeholder="Age">
        </div>
        <div classname="mt-6 text-right">
          <button disabled classname="bg-green-600 text-white px-5 py-1 text-base disabled:opacity-30">
            {isPending ? "Adding" : "Add User"}
          </button>
        </div>

        {(state?.error as string) && <p>{state.error as string}</p>}
      </form>
    </div>
  );
}

Kemas kini src/app/serverexample/page.tsx untuk memasukkan komponen AddUser:

import UserList from "./UserList";
// Import new line
import AddUser from "./AddUser";
import "./App.css"

export default async function ServerPage() {
  return (
    <div classname="app">
      <header classname="App-header">
        <userlist></userlist>
        {/* insert Add User here */}
        <adduser></adduser>
      </header>
    </div>
  );
}

Menjalankan aplikasi kini membolehkan anda menambah pengguna baharu melalui borang, dengan pemprosesan bahagian pelayan dikendalikan dengan lancar.
React - Server Actions

The AddUser Component and Seamless Client-Server Interaction

The AddUser component is at the heart of this example, showcasing how React Server Actions can revolutionize the way we handle client-server interactions. This component renders a form for adding new users and leverages the useActionState hook to create a smooth and seamless bridge between the client-side interface and server-side operations.

How It Works

  1. Form Rendering and Data Handling:
  • The AddUser component provides a form where users can input their name, email, and age.
  • Upon form submission, the data is captured and prepared to be sent to the server.
  1. useActionState Hook:
  • The useActionState hook is a crucial part of this setup. It simplifies the complexity of managing client-side state and server-side actions by abstracting them into a unified interface.
  • This hook accepts an asynchronous handler function, which processes the form data and then calls a Server Action method.
  • The brilliance of this approach lies in its abstraction: it feels as though you’re invoking a regular function within the same file, even though it actually triggers a server-side operation.
  1. Server Action Method:
  • The createUser function, defined as a Server Action, executes on the server side. It takes the user data from the form, performs the necessary database operations via Prisma, and returns the result.
  • This server-side method is crucial for maintaining a clean separation between the client and server, while still enabling them to communicate effectively.
  1. Seamless Integration:

From the perspective of a developer working on the client side, it appears as if the form submission is handled locally. However, the heavy lifting such as database manipulation occurs on the server.
The useActionState hook encapsulates this process, managing the state transitions and handling errors, while maintaining an intuitive API for developers.

Server Actions Without Forms

So that's with forms, now lets test an example without forms.
update src/app/serverexample/UserDetail.tsx

"use client";
import { deleteUser } from "@/actions/user";
import { useTransition } from "react";

export function UserDetail({ user }) {
  const [pending, startTransition] = useTransition();

  const handleDelete = () => {
    startTransition(() => {
      deleteUser(user.id);
    });
  };

  return (
    <div classname="flex items-center gap-4 border border-gray-600 py-1 px-4">
      {pending ? (
        <p>Deleting...</p>
      ) : (
        
          <img classname="w-10 h-10 rounded-full" src="https://api.dicebear.com/9.x/personas/svg?seed=Shadow" alt="React - Tindakan Pelayan">
          <div classname="font-medium text-base dark:text-white">
            <div>{user.name}</div>
            <div classname="text-sm text-gray-500 dark:text-gray-400">
              {user.email}
            </div>
          </div>
          <button classname="ml-auto" onclick="{handleDelete}">
            <img classname="w-4 h-4" src="/delete.png" alt="">
          </button>
        >
      )}
    </div>
  );
}

Key Points:

  • Server Action: deleteUser(user.id) is a server action that removes the user from the database. This operation is triggered without any form submission.
  • useTransition: This hook allows you to manage the asynchronous state of the deletion process, showing a "Deleting..." message while the operation is in progress.
  • User Interface: The component maintains a clean UI, dynamically updating based on the action status.

Now, you can seamlessly delete a user within the application:
React - Server Actions

Conclusion

This approach is transformative because it abstracts away the complexities of client-server communication. Traditionally, such interactions would require handling API endpoints, managing asynchronous requests, and carefully coordinating client-side state with server responses. With React Server Actions and the useActionState hook, this complexity is reduced, allowing developers to focus more on building features rather than worrying about the underlying infrastructure.

By using this pattern, you gain:

  • Cleaner Code: The client-side code remains simple and focused, without the need for explicit API calls.
  • Improved Developer Experience: Server-side operations are seamlessly integrated, reducing cognitive load and potential for errors.
  • Enhanced Performance: Server Actions are optimized for performance, reducing unnecessary client-server round trips and ensuring that server-side resources are used efficiently.

You can find the full code in the repository

Atas ialah kandungan terperinci React - Tindakan Pelayan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel sebelumnya:Pekerja PerkhidmatanArtikel seterusnya:Pekerja Perkhidmatan