为什么在调用 react router dom 中的 useActionData() 时没有使用对象解构?

huangapple go评论67阅读模式
英文:

Why is it not object destructuring when calling useActionData() in react router dom?

问题

当我调用useActionData()时,我没有得到任何对象的解构。当我在控制台上打印时,我得到了name: 'isakGo'。代码如下:

export async function action({ request }) {
  const formData = await request.formData();
  const name = { name: formData.get("name") };
  return { name };
}

export default function FormTest() {
  const { name } = useActionData(); // 这里发生了错误

  // 其他代码
}

我们正在使用createBrowserRouter()创建路由,并使用RouterBrowser进行服务。

const router = createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    errorElement: <ErrorPage />,
    children: [
      {
        path: "/FormTest",
        element: <FormTest />,
        action: formTestAction,
      },
    ],
  },
]);

发生了以下错误。
> 无法解构(0, react_router_dom__WEBPACK_IMPORTED_MODULE_1__.useActionData)(...)的属性'name',因为它未定义。

如果将代码更改为不进行对象解构的代码,它将正常工作。

export async function action({ request }) {
  const formData = await request.formData();
  const name = { name: formData.get("name") };
  return name;
}

export default function FormTest() {
  const name = useActionData(); 

  // 其他代码
}

当我在react-router-dom中写像loader()这样的东西时,即const { name } = useLoaderData();,它可以正常工作。action()没有破坏对象。我漏掉了什么?

我正在使用create-react-appreact-router-dom@6.11.2版本。

编辑

我们发现可能直接与错误相关的其他因素。

  1. 当加载FormTest()时,会调用useActionData(),因此空的name变量为空。
  2. 由于某种原因,当我将结果打印到控制台时,它被调用了4次。
英文:

When I call useActionData(), I don't get any object destruction. When I print to the console, I get name: 'isakGo'. The code looks like this

export async function action({request}) {
  const formData = await request.formData();
  const name = { name: formData.get(&quot;name&quot;) }
  return { name };
}

export default function FormTest() {
  const { name } = useActionData(); // error has occured here

  // other codes
}

We're creating a router with createBrowserRouter() and serving it with RouterBrowser.

const router = createBrowserRouter([
  {
    path: &quot;/&quot;,
    element: &lt;Root /&gt;,
    errorElement: &lt;ErrorPage /&gt;,
    children: [
      {
        path: &quot;/FormTest&quot;,
        element: &lt;FormTest /&gt;,
        action: formTestAction,
      }
    ]
  },
])

The following error occurs.
> Cannot destructure property 'name' of '(0 , react_router_dom__WEBPACK_IMPORTED_MODULE_1__.useActionData)(...)' as it is undefined.

If you change your code to one that doesn't do object destruction, it will work cleanly.

export async function action({request}) {
  const formData = await request.formData();
  const name = { name: formData.get(&quot;name&quot;) }
  return name;
}

export default function FormTest() {
  const name = useActionData(); 

  // other codes
}

When I write something like loader() in react router dom, i.e. const { name } = useLoaderData();, it works fine. action() is not destroying the object. what am I missing?

I'm using the create-react-app and the react-router-dom@6.11.2 version.

Edit

We found additional factors that may be directly related to the error.

  1. useActionData() is called when FormTest() is loaded, so the empty name variable is empty.
  2. for some reason, it is called 4 times when I print the results to the console.

答案1

得分: 1

文档

> 此钩子提供了前一次导航操作结果的返回值,如果没有提交,则返回 undefined。

function SomeComponent() {
  let actionData = useActionData();
  // ...
}

> 此钩子的最常见用例是表单验证错误。如果表单不正确,您可以返回错误并让用户重试:

代码示例

import {
  useActionData,
  Form,
  redirect,
} from "react-router-dom";

export default function SignUp() {
  const errors = useActionData();

  return (
    <Form method="post">
      <p>
        <input type="text" name="email" />
        {errors?.email && <span>{errors.email}</span>}
      </p>

      <p>
        <input type="text" name="password" />
        {errors?.password && <span>{errors.password}</span>}
      </p>

      <p>
        <button type="submit">Sign up</button>
      </p>
    </Form>
  );
}

export async function action({ request }) {
  const formData = await request.formData();
  const email = formData.get("email");
  const password = formData.get("password");
  const errors = {};

  // 验证字段
  if (typeof email !== "string" || !email.includes("@")) {
    errors.email =
      "那不像是一个电子邮件地址";
  }

  if (typeof password !== "string" || password.length < 6) {
    errors.password = "密码必须大于6个字符";
  }

  // 如果有错误则返回数据
  if (Object.keys(errors).length) {
    return errors;
  }

  // 否则创建用户并重定向
  await createUser(email, password);
  return redirect("/dashboard");
}
英文:

Documentation

> This hook provides the returned value from the previous navigation's action result, or undefined if there was no submission.

function SomeComponent() {
  let actionData = useActionData();
  // ...
}

> The most common use-case for this hook is form validation errors. If the form isn't right, you can return the errors and let the user try again:

Code Example

import {
  useActionData,
  Form,
  redirect,
} from &quot;react-router-dom&quot;;

export default function SignUp() {
  const errors = useActionData();

  return (
    &lt;Form method=&quot;post&quot;&gt;
      &lt;p&gt;
        &lt;input type=&quot;text&quot; name=&quot;email&quot; /&gt;
        {errors?.email &amp;&amp; &lt;span&gt;{errors.email}&lt;/span&gt;}
      &lt;/p&gt;

      &lt;p&gt;
        &lt;input type=&quot;text&quot; name=&quot;password&quot; /&gt;
        {errors?.password &amp;&amp; &lt;span&gt;{errors.password}&lt;/span&gt;}
      &lt;/p&gt;

      &lt;p&gt;
        &lt;button type=&quot;submit&quot;&gt;Sign up&lt;/button&gt;
      &lt;/p&gt;
    &lt;/Form&gt;
  );
}

export async function action({ request }) {
  const formData = await request.formData();
  const email = formData.get(&quot;email&quot;);
  const password = formData.get(&quot;password&quot;);
  const errors = {};

  // validate the fields
  if (typeof email !== &quot;string&quot; || !email.includes(&quot;@&quot;)) {
    errors.email =
      &quot;That doesn&#39;t look like an email address&quot;;
  }

  if (typeof password !== &quot;string&quot; || password.length &lt; 6) {
    errors.password = &quot;Password must be &gt; 6 characters&quot;;
  }

  // return data if we have errors
  if (Object.keys(errors).length) {
    return errors;
  }

  // otherwise create the user and redirect
  await createUser(email, password);
  return redirect(&quot;/dashboard&quot;);
}

huangapple
  • 本文由 发表于 2023年6月6日 16:18:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76412676.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定