如何在 React Router 中处理同一表单上的两个不同操作

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

我有以下 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
唉,不。

react-router
1个回答
0
投票

如果“清晰”功能是您唯一的问题,则无需任何外部途径即可实现。尝试更改您的代码,例如:

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>
    </>
  );
}
© www.soinside.com 2019 - 2024. All rights reserved.