文章
useActionState案例
/src/app/user/[userId]/page.tsx
服务端组件根据路由动态传参将userId传给客户端组件
import {UserProfile} from "@/components/user-profile";
export default async function Page({params}: { params: Promise<{ userId: string }> }) {
const {userId} = await params
return (
<UserProfile userId={userId}/>
)
}
/src/components/user-profile.tsx
客户端组件将userId绑定到server action:updateUser
'use client'
import { updateUser, FormState } from '@/app/actions'
import { useActionState } from "react";
export function UserProfile({ userId }: { userId: string }) {
const updateUserWithId = updateUser.bind(null, userId);
const initialState: FormState = {
message: "",
};
const [state, formAction, pending] = useActionState<FormState, FormData>(
updateUserWithId,
initialState
);
return (
<form action={formAction}>
<input type="text" name="name"/>
<p aria-live="polite">{state?.message}</p>
<button type="submit" disabled={pending}>Update User Name</button>
</form>
)
}
/src/app/actions.ts
因为自定义了userId同时还要接受useActionState传参,第一个参数是 自定义的userId,后面才是useActionState的传参,最后是FormData
"use server"
export type FormState = {
message: string;
};
export async function updateUser(
userId: string,
prevState: FormState,
formData: FormData
): Promise<FormState> {
console.log(userId, formData);
return { message: "Updated successfully" };
}
这里action返回值会传给下面的state
const [state, formAction, pending] = useActionState<FormState, FormData>(
updateUserWithId,
initialState
);
后续调用:{state?.message}
绑定userId写法也可以这样写:
const updateUserWithId = async (prevState: FormState, formData: FormData) => {
return updateUser(prevState, userId, formData);
};
这么写可以自定义updateUser的参数顺序,对应以上写法,updateUser需要改写如下:
export async function updateUser(
prevState: FormState,
userId: string,
formData: FormData
): Promise<FormState> {
console.log(userId, formData);
return { message: "Updated successfully" };
}
也就是useActionState还是给updateUserWithId函数传参(prevState: FormState, formData: FormData) 第一个还是prevState,只是实际我们调用的updateUser参数顺序是按照我们自己的来定义。