我在 React 应用程序中有一个表单。我正在使用
useActionState
挂钩来管理表单状态。如何将提交按钮设置为禁用,直到用户在文本输入中输入内容?
通过使用
useState
钩子存储输入并在输入更改时调用 setter 方法,我可以跟踪表单字段中是否有输入。但是通过使用 useActionState
我只能在提交表单后才能知道表单值。
import { useActionState, useState } from "react";
export function MyForm() {
// form state managed with useActionState
const [state, formAction] = useActionState(
updateState,
{ name: ""}
)
function updateState(_prevState, formData) {
// do something
return {name: formData.get("name") as string}
}
// form state managed with useState
const [state2, setState2] = useState({name: ""})
function handleChange(e) {
setState2({name: e.target.value})
}
function handleSubmit(e) {
e.preventDefault()
// do something
setState2({name: ""})
}
return (
<>
{/* form state managed with useActionState */}
<form action={formAction}>
<input type="text" name="name" />
<button type="submit">Submit</button> {/* <- I want this to be disabled until user enters a value */}
<div>{state.name}</div>
</form>
{/* form state managed with useState */}
<form onSubmit={handleSubmit}>
<input type="text" name="name" onChange={handleChange} value={state2.name}/>
<button disabled={state2.name ? false : true} type="submit">Submit</button>
<div>{state2.name}</div>
</form>
</>
)
}
我知道有一个钩子
useFormStatus
可能用于此目的,但我不喜欢将表单内容放在单独的子组件中的想法。
useActionState
和useFormStatus
钩子都为您提供了一些在提交后使用表单状态的方法。它们都不能让您在提交表格之前与各州合作。因此,如果您想在输入为空时禁用按钮,则需要使用 useState
检查输入的值并在任何更改时禁用按钮。例如:
import { useActionState, useState } from "react";
export function MyForm() {
// form state managed with useActionState
const [state, formAction] = useActionState(
updateState,
{ name: ""}
)
function updateState(_prevState, formData) {
// do something
return {name: formData.get("name") as string}
}
// form state managed with useState
const [inputValue, setInputValue] = useState(null)
function handleChange(e) {
setInputValue(e.currentTarget.value)
}
return (
<form action={formAction}>
<input type="text" name="name" onChange={handleChange} />
<button type="submit" disabled={!inputValue}>Submit</button>
<div>{state.name}</div>
</form>
)
}