我有以下 React Ruoter 路由表:
const router = createBrowserRouter(
[
{
path: "/",
element: <Root />,
errorElement: <ErrorPage />,
loader: rootLoader,
children: [
{
errorElement: <ErrorPage />,
children: [
{ index: true, element: <Index /> },
{
path: "foo/:uid",
element: <Foo />,
loader: fooLoader,
},
{
path: "foo/:uid/update",
element: <Foo />,
action: updateAction,
},
{
path: "foo/:uid/clear",
element: <Foo />,
action: clearAction,
},
],
},
],
},
],
);
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>,
);
Foo
组件是一个简单的表单,有2个按钮:Submit
和Clear
export async function action({ request, params }) {
console.log(`${request}`);
return redirect(`/provider/${params.uid}`);
}
export default function Foo() {
const navigation = useNavigation();
function handleOnClickClear(event) {
if (!confirm("Please confirm you want to clear embeddings")) {
event.preventDefault();
}
}
return (
<>
<Form action="update" method="post" id="foo-form">
<input id="label" name="label" placeholder="Label" />
<textarea
id="text"
name="text"
placeholder="Text"
rows="5"
cols="80"
wrap="soft"
required
></textarea>
<button type="submit">Submit</button>
<button
type="submit"
form="foo-form"
formAction="clear"
onClick={handleOnClickClear}
>
Clear
</button>
</Form>
</>
);
}
当单击
Submit
按钮时,将调用上述组件中的 action
,因为它在路由器上指定为 updateAction
(导入类似于 import {action as updataAction} from...
)
我想在单击
Clear
按钮时执行与 Submit
操作不同的操作(例如,为了简单起见,清除文本区域 - 实际上,清除实际上会触发 API 请求,但清除某些内容)显示的页面可以很好地用于说明),因此我给了它 formAction="clear"
属性,我希望该属性会导致应用程序向我为 foo/:uid/clear
路线指定的路线发送请求。 clearAction
代码现在非常简单,用于调试目的:
import { redirect } from "react-router-dom";
export async function action({ params }) {
console.log(`Clearing provider ${params.uid}`);
return redirect(`provider/${params.uid}`);
}
当我单击
Clear
按钮时,应用程序会忽略路由表中的操作分配,并且应用程序失败并显示:
ErrorResponseImpl {status: 405, statusText: 'Method Not Allowed', internal: true, data: "Error: You made a POST request to \"/foo/0b3123f3-48bb-429a-874c-9d4b23320ff3\" but did not provide an `action` for route \"0-0-1\", so there is no way to handle the request.
所以看来这不是正确的方法。我怀疑如果我将这两个按钮分成单独的反应路由器
Form
的东西可能开始工作,但是有没有办法用一个表单和两个单独的按钮来做到这一点?
更新: 我认为我可能需要做的是将额外的路线与其操作进行合并,并使用类似 https://reactrouter.com/en/main/hooks/use-fetcher 的内容来完全避免导航。
Update2: 使用
fetcher.Form
具有与上面相同(或至少相似)的效果——不知何故,React Router 无法将请求路由到 Foo
action
并失败并显示
Error: You made a POST request to "/foo/f6799ce3-7b13-46e0-98bd-334f1edb49ce" but did not provide an `action` for route "0-0-1", so there is no way to handle the request.
我希望这会“路由”到相同的应用程序路线,从而由该路线上的
action
处理:updateAction
唉,不。
如果“清晰”功能是您唯一的问题,则无需任何外部途径即可实现。尝试更改您的代码,例如:
export default function Foo() {
const navigation = useNavigation();
const textFieldRef = useRef(null);
function onClearClick() {
textFieldRef.current.value = "";
}
return (
<>
<Form action="update" method="post" id="foo-form">
<input id="label" name="label" placeholder="Label" />
<textarea
id="text"
ref={textFieldRef}
name="text"
placeholder="Text"
rows="5"
cols="80"
wrap="soft"
required
></textarea>
<button type="submit">Submit</button>
<input
type="button"
onClick={onClearClick}
>
Clear
</button>
</Form>
</>
);
}