Remix提交表单onChange,并从useActionData()获得实时更新



我试图创建一个混音页面,我想得到实时预览,当我改变一个Select标签。它正在通过一个表单,因为我想让它转换数据。

解决我的问题可能是使preventDefault(第一个代码示例)工作或找到一种方法使useActionData()(第二个代码示例)在使用useFetcher时工作

在此代码中,preventDefault不起作用。我需要preventDefault工作,使选择器不重置。我可以让action函数也发送名称,这样select中的DefaultValue就会从action函数中导入,但是这将成为一个大表单,我不想刷新整个页面。

export async function action({ request }: ActionArgs) {
const form = new URLSearchParams(await request.text())
const name = form.get('name');
console.log('name', name);
return json({ message: name ? `Hello ${name}!` : 'Select name' });
}
export default function Page() {
const actionData = useActionData();
console.log('actionData', actionData);
return (
<>
<Form method="post">
<h1>{actionData ? actionData.message : 'Select name.'}</h1>
<select 
name="name" 
onChange={e => {
e.preventDefault();
e.target.form.submit();
}}
>
<option value="name 1">Name 1</option>
<option value="name 2">Name 2</option>
<option value="name 3">Name 3</option>
</select>
<button type="submit" className="bg-blue-500 text-white font-bold py-2 px-4">
Submit
</button>
</Form>
</>
);
}

我也尝试使用useRef and useFetcher遵循https://github.com/remix-run/remix/issues/1807,但即使动作函数运行,它给我undefined时记录actionData。

export async function action({ request }: ActionArgs) {
const form = new URLSearchParams(await request.text())
const name = form.get('name');
console.log('name', name);
return json({ message: name ? `Hello ${name}!` : 'Select name' });
}
export default function Page() {
const actionData = useActionData();
console.log('actionData', actionData); // Gives undefined
const formRef = useRef<HTMLFormElement>(null);
const fetcher = useFetcher();
return (
<>
<fetcher.Form method="post" ref={formRef}>
<h1>{actionData ? actionData.message : 'Select name.'}</h1>
<select 
name="name" 
onChange={() => {
fetcher.submit(formRef.current);
}}
>
<option value="name 1">Name 1</option>
<option value="name 2">Name 2</option>
<option value="name 3">Name 3</option>
</select>
<button type="submit" className="bg-blue-500 text-white font-bold py-2 px-4">
Submit
</button>
</fetcher.Form >
</>
);
}

我找到了一个解决方案,它是使用fetcher。加载,然后将其作为自己的加载器文件。

主文件test.tsx:

import { useFetcher } from '@remix-run/react';
export default function Page() {
const fetcher = useFetcher();
return (
<>
<div>
<h1>{fetcher.data ? fetcher.data.message : 'Select name.'}</h1>
<select
name="name"
onChange={e => {
fetcher.load(`loader/?name=${e.target.value}`);
}} 
>
<option value="name 1">Name 1</option>
<option value="name 2">Name 2</option>
<option value="name 3">Name 3</option>
</select>
<button type="submit" className="bg-blue-500 text-white font-bold py-2 px-4">
Submit
</button>
</div>
</>
);
}

Loaderfile loader.ts:

import type { LoaderArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
export async function loader({ request }: LoaderArgs) {
const form = new URLSearchParams(await request.text());
const name = form.get('name');
return json({ message: name ? `Hello ${name}!` : 'Select name' });
}

最新更新