useFormState 的强类型保证

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

我将 React 的

useFormState
钩子与 NextJS 一起使用,几乎如官方文档示例项目中所述:

"use client";

import { serverFunction } from "@/app/actions";
import { useFormState, useFormStatus } from "react-dom";

const initialState = "";

function SubmitButton() {
  const { pending } = useFormStatus();

  return (
    <button type="submit" aria-disabled={pending}>
      Add
    </button>
  );
}


export default function Example() {
  const [state, formAction] = useFormState(serverFunction, initialState);

  return (
    <div>
      <form action={formAction}>
        <input type="file" name="image" />
        <SubmitButton />
        <pre>{JSON.stringify(state, null, 2)}</pre>
      </form>
    </div>
  );
}

actions.ts
我有:

"use server";

export async function serverFunction(_: unknown, formData: FormData) {
  const imgFile = formData.get("image");
  // ... some processing
}

但是,此方法不使用静态类型检查来确保客户端上表单提供的数据与服务器期望的数据相对应。我该如何在这个玩具示例中引入它?

(当然,我可以使用像

fp-ts
zod
这样的库进行运行时验证,但这不是这个问题的目的)。

reactjs typescript forms next.js
1个回答
0
投票

useFormState
<form action={}>
构建于
FormData
之上,它不采用泛型类型参数。所以你运气不好。

如果您想要静态类型并且愿意尝试类似的操作,您可以使用常规服务器操作:

'use client';

import { useState } from 'react';
import { createUser } from './user';

const initialState = {
  email: '',
  message: '',
};

export default function Signup() {
  const [state, setState] = useState(initialState);

  return (
    <form
      onSubmit={(event) => {
        event.preventDefault();
        void createUser(state).then(setState);
      }}
    >
      <label htmlFor="email">Email</label>
      <input
        type="email"
        name="email"
        required
        value={state.email}
        onChange={(event) => setState({ ...state, email: event.target.value })}
      />

      {state.message && <p>{state.message}</p>}

      <button type="submit">Sign up</button>
    </form>
  );
}

用户.ts

'use server';

export type UserFormInput = {
  email: string;
};

export async function createUser(input: UserFormInput) {
  if (!input.email.includes('@')) {
    return {
      ...input,
      message: 'Invalid email address',
    };
  }

  return {
    ...input,
    message: 'User created',
  };
}

请参阅工作示例:https://stackblitz.com/edit/stackoverflow-78124489

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