简化的Reaction组件,形式如下:
const itemSchema = z.object({
title: z.string().max(50),
});
type ItemFormFields = z.infer<typeof itemSchema>;
const {
register,
handleSubmit,
reset,
setError,
formState: { isSubmitting, errors }
} = useForm<ItemFormFields>({
defaultValues: {
title: "title placehnolder"
},
resolver: zodResolver(itemSchema)
});
// RTK's isLoading and error remain not updated for mutation hooks
// but the same work as expected with query hooks done through .initialize() in RRv6 loader
// const [_createItem, { isLoading, error }] = useCreateItemMutation();
const submit = useSubmit();
const actionData = useActionData<typeof itemsAction>();
const hasError = actionData && 'error' in actionData && isString(actionData.error);
useEffect(() => {
if (hasError) {
const { error } = actionData;
setError('root', {
message: error
});
}
}, [actionData, hasError, setError]);
return (
<div className="new-item">
<Form
onSubmit={(event: React.FormEvent<HTMLFormElement>) => {
handleSubmit((data: ItemFormFields) => {
submit(data, { method: 'post' });
reset();
})(event);
}}
>
<div className="new-item__form-body">
<div>
<div>
<label htmlFor="title">Title:</label>
</div>
{errors.title && <div>{errors.title.message}</div>}
</div>
<div>
<div>
<input
id="title"
type="text"
required
{...register('title')}
/>
</div>
</div>
</div>
<div className="new-item__form-footer">
<Button
disabled={isSubmitting}
type="submit"
>
{isSubmitting ? 'Loading...' : 'Submit'}
</Button>
</div>
{errors.root && <div>{errors.root.message}</div>}
</Form>
</div>
);
react 路由操作功能:
import { ActionFunction, ActionFunctionArgs, redirect } from 'react-router-dom';
// ...
const fromEntries = <T extends object>(data: FormData) => Object.fromEntries<string | number | File>(data) as T;
export const itemsAction = (async ({ request }: ActionFunctionArgs) => {
const data: FormData = await request.formData();
const formData: ItemFormFields = fromEntries(data);
const mutation = store.dispatch(api.endpoints.createItem.initiate(formData));
try {
const { id } = await mutation.unwrap();
return redirect(`/items/${id}`);
} catch (error) {
return {
error: 'Post-Validation error message placeholder'
};
}
}) satisfies ActionFunction;
除了Reaction Hook isSubmitting
之外,所有内容都是一样的,它仍然是未订阅和错误/未定义的.如果我try 使用RTK,则与来自Const [_createItem, { isLoading, error }] = useCreateItemMutation();
的isLoading, error
相同.
UseForm数据成功地通过handleSubmit
和RRv6 submit
提交-该操作成功地获取了具有正确Zod架构类型ItemFormFields
的formData
.RTKMutations 启动器成功地将一个新实体发布到数据库,然后数据库在响应中返回ID,并且RRv6redirect
发生,其中它成功地通过加载器获取并且一切顺利……除了useForm
中的isSubmitting
个FormState仍然是未订阅的,RTK的isLoding也是未定义的.在常规的异步示例中,isSubmitting
的工作方式与预期相同,但一旦它从Reaction路由6从useSubmit
转到action
至void submit
,它就永远不会订阅,也永远不会更新到true
.我假设它需要Promise
,但RR6的S useSubmit
提供了一个常规的空白,并在幕后完成了整个流程.
编辑:只需普通的Reaction路由6(浏览器数据路由),具有/new的路由:
{
path: 'new',
element: <NewItem />,
action: itemsAction
}