在NextJS中通过useTransition()调用异步函数时没有得到返回

问题描述 投票:0回答:1

我使用 NextJS 14 和 Shadcn 作为组件。我有一个带有表单的组件,它使用 useTransition 挂钩将表单数据发送到操作,然后在数据中获取成功或错误返回。但是,当我调用该操作时,数据库会更新(这是为了更新数据库中的名称),但 .then(data) 返回没有收到返回值。

我发送数据的表单组件是:

'use client';

import * as z from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { useTransition, useState } from 'react';
import { toast } from 'react-toastify';

import {
    Form,
    FormControl,
    FormField,
    FormItem,
    FormMessage
} from '@/components/ui/form';

import { SubmitButton } from '@/components/form/Buttons';
import { UserProps } from '@/utils/types';
import { AccountFormInput } from '@/components/form/FormInput';
import FormError from '@/components/form/FormError';
import { NameSchema } from '@/schemas';
import { cn } from '@/lib/utils';
import { updateName } from '@/actions/personalInfo';

const NameForm = ({ user }: UserProps) => {
    const [edit, setEdit] = useState(false);
    const [error, setError] = useState<string | undefined>('');
    const [isPending, startTransition] = useTransition();

    const errorClass = 'pl-6';
    const userEmail = user?.email!;

    const form = useForm<z.infer<typeof NameSchema>>({
        resolver: zodResolver(NameSchema),
        defaultValues: {
            firstName: user?.firstName || '',
            lastName: user?.lastName || ''
        }
    });

    const cancel = () => {
        setEdit(!edit);
        form.reset();
    };

    const onSubmit = (values: z.infer<typeof NameSchema>) => {
        setError('');

        startTransition(() => {
            updateName(values, userEmail).then((data) => {
                console.log('data - ' + data);

                if (data?.error) {
                    setError(data.error);
                }

                if (data?.success) {
                    form.reset();
                    setEdit(false);
                    toast.success('Name successfully updated');
                }
            });
        });
    };

    return (
        <div className="flex flex-col gap-5 border-b border-b-gray-200 pb-8">
            <div className="flex justify-between">
                <h3 className="font-semibold text-base">Name</h3>
                <div
                    className="cursor-pointer text-base font-normal hover:underline"
                    onClick={cancel}
                >
                    {edit ? 'Cancel' : 'Edit'}
                </div>
            </div>
            {edit ? (
                <Form {...form}>
                    <FormError message={error} />
                    <form
                        className="space-y-6 w-full"
                        onSubmit={form.handleSubmit(onSubmit)}
                    >
                        <input
                            type="hidden"
                            name="userEmail"
                            value={user?.email!}
                        />
                        <div className="flex flex-row gap-x-6">
                            <FormField
                                control={form.control}
                                name="firstName"
                                render={({ field }) => (
                                    <FormItem className={cn('w-full')}>
                                        <FormControl>
                                            <AccountFormInput
                                                {...field}
                                                name="firstName"
                                                type="text"
                                                placeholder="First Name"
                                            />
                                        </FormControl>
                                        <FormMessage className={errorClass} />
                                    </FormItem>
                                )}
                            />
                            <FormField
                                control={form.control}
                                name="lastName"
                                render={({ field }) => (
                                    <FormItem className={cn('w-full')}>
                                        <FormControl>
                                            <AccountFormInput
                                                {...field}
                                                name="lastName"
                                                type="text"
                                                placeholder="Last Name"
                                            />
                                        </FormControl>
                                        <FormMessage className={errorClass} />
                                    </FormItem>
                                )}
                            />
                        </div>
                        <div className="flex-1">
                            <SubmitButton text="update" isPending={isPending} />
                        </div>
                    </form>
                </Form>
            ) : (
                <div
                    className={`${
                        !user?.firstName && 'italic'
                    } text-base font-normal`}
                >
                    {user?.firstName && user?.lastName
                        ? `${user.firstName} ${user.lastName}`
                        : 'Not specified'}
                </div>
            )}
        </div>
    );
};
export default NameForm;

我的行动是:

'use server';

import * as z from 'zod';

import db from '@/lib/db';
import { NameSchema } from '@/schemas';
import { getUserByEmail } from '@/data/user';

export const updateName = async (
    values: z.infer<typeof NameSchema>,
    email: string
) => {
    const validatedFields = NameSchema.safeParse(values);

    if (!validatedFields.success) {
        return { error: 'Invalid fields!' };
    }

    const { firstName, lastName } = validatedFields.data;

    const existingUser = await getUserByEmail(email!);

    if (!existingUser) {
        return { error: 'User does not exist!' };
    }

    await db.user.update({
        where: { id: existingUser.id },
        data: {
            firstName,
            lastName
        }
    });

    return { success: 'Name updated' };
};

我是否缺少某些内容来查看为什么我没有得到回复?

reactjs next.js react-hooks nextjs14 shadcnui
1个回答
0
投票

这是因为 startTransition API 不是异步的,并且你的 .then() 返回一个承诺。

因此 startTransition 正在运行并立即返回,但您的函数仍在等待答案

© www.soinside.com 2019 - 2024. All rights reserved.