如何在NextJS中使用tRPC进行API请求而不出现无效的钩子调用错误

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

How to make an API request with tRPC and NextJS without an invalid hook call error

问题

以下是代码部分的翻译:

my zip code component

  1. 'use client';
  2. import { type NextPage } from "next"
  3. import { NextPageButtonLink } from "../UI/NextPageButtonLink"
  4. import { api } from "../utils/api"
  5. import { useState } from "react"
  6. const ZipCode: NextPage = () => {
  7. const [zip code, setZipCode] = useState("");
  8. // This posts on every rerender and input. Ideally, it should only post when the user clicks submit
  9. // const postZipCodeResult = API.zipcode.postZipCode.use query({userId: "1", zipcode: zipcode});
  10. const handleSubmit = () => {
  11. // This throws the invalid hook location error
  12. const postZipCodeResult = API.zipcode.postZipCode.use query({userId: "1", zipcode: zipcode});
  13. console.log("Posting result", postZipCodeResult)
  14. }
  15. return (
  16. <div className="bg-[#3276AE] flex flex-col items-center h-screen">
  17. <form onSubmit={handleSubmit}>
  18. <label htmlFor="zipcode">Enter your zipcode:
  19. <input type="text" id="zipcode" name="zipcode" required value={zipcode} onChange={e => setZipCode(e.target.value)} />
  20. </label>
  21. <button type="submit">Submit</button>
  22. </form>
  23. <NextPageButtonLink pageName="survey" msg="Click here to start the demographics survey." />
  24. </div>
  25. )
  26. }
  27. export default ZipCode;

My zip code page:

  1. import dynamic from "next/dynamic";
  2. const ZipCode = dynamic(() => import('components/zipcode'), {
  3. SSR: false
  4. })
  5. export default function ZipCodePage() {
  6. return (<ZipCode/>)
  7. }

my zip code router

  1. import { z } from "zod";
  2. import { createTRPCRouter, publicProcedure } from "../trpc";
  3. export const zipcodeRouter = createTRPCRouter({
  4. postZipCode: publicProcedure
  5. .input(z.object({ userId: z.string(), zipcode: z.string() }))
  6. .query(({ input }) => {
  7. return {
  8. zipcode: `User: ${input.userId} zipcode: ${input.zipcode}`,
  9. };
  10. }),
  11. });
英文:

I'm trying to send user input data to my tRPC API. When I try to send my query, I get an error that I can only use React Hooks inside a function component. I believe I can't call tRPC's useQuery from a callback because it's a react hook, but how can I submit the mutation when the form is completed?

my zip code component

  1. &#39;use client&#39;;
  2. import { type NextPage } from &quot;next&quot;
  3. import { NextPageButtonLink } from &quot;../UI/NextPageButtonLink&quot;
  4. import { api } from &quot;../utils/api&quot;;
  5. import { useState } from &quot;react&quot;;
  6. const ZipCode: NextPage = () =&gt; {
  7. const [zip code, setZipCode] = useState(&quot;&quot;);
  8. // This posts on every rerender and input. Ideally, it should only post when the user clicks submit
  9. // const postZipCodeResult = API.zipcode.postZipCode.use query({userId: &quot;1&quot;, zipcode: zipcode});
  10. const handleSubmit = () =&gt; {
  11. // This throws the invalid hook location error
  12. const postZipCodeResult = API.zipcode.postZipCode.use query({userId: &quot;1&quot;, zipcode: zipcode});
  13. console.log(&quot;Posting result&quot;, postZipCodeResult)
  14. }
  15. return (
  16. &lt;div className=&quot;bg-[#3276AE] flex flex-col items-center h-screen&quot;&gt;
  17. &lt;form onSubmit={handleSubmit}&gt;
  18. &lt;label htmlFor=&quot;zipcode&quot;&gt;Enter your zipcode:
  19. &lt;input type=&quot;text&quot; id=&quot;zipcode&quot; name=&quot;zipcode&quot; required value={zipcode} onChange={e =&gt; setZipCode(e.target.value)} /&gt;
  20. &lt;/label&gt;
  21. &lt;button type=&quot;submit&quot;&gt;Submit&lt;/button&gt;
  22. &lt;/form&gt;
  23. &lt;NextPageButtonLink pageName=&quot;survey&quot; msg=&quot;Click here to start the demographics survey.&quot; /&gt;
  24. &lt;/div&gt;
  25. )
  26. }
  27. export default ZipCode;

My zip code page:

  1. import dynamic from &quot;next/dynamic&quot;;
  2. const ZipCode = dynamic(() =&gt; import(&#39;../components/zipcode&#39;), {
  3. SSR: false
  4. })
  5. export default function ZipCodePage() {
  6. return (&lt;ZipCode/&gt;)
  7. }

my zip code router

  1. import { z } from &quot;zod&quot;;
  2. import { createTRPCRouter, publicProcedure } from &quot;../trpc&quot;;
  3. export const zipcodeRouter = createTRPCRouter({
  4. postZipCode: publicProcedure
  5. .input(z.object({ userId: z.string(), zipcode: z.string() }))
  6. .query(({ input }) =&gt; {
  7. return {
  8. zipcode: `User: ${input.userId} zipcode: ${input.zipcode}`,
  9. };
  10. }),
  11. });

答案1

得分: 3

你不能有条件地调用钩子,但你可以禁用查询,然后在用户点击按钮时使用它的 refetch 来触发它。

  1. const ZipCode: NextPage = () => {
  2. const [zipcode, setZipCode] = useState("");
  3. const { data, refetch } = api.zipcode.postZipCode.useQuery({ userId: "1", zipcode: zipcode }, {
  4. enabled: false
  5. });
  6. const handleSubmit = () => {
  7. refetch();
  8. }
  9. return (
  10. <div className="bg-[#3276AE] flex flex-col items-center h-screen">
  11. <form onSubmit={handleSubmit}>
  12. <label htmlFor="zipcode">Enter your zipcode:
  13. <input type="text" id="zipcode" name="zipcode" required value={zipcode} onChange={e => setZipCode(e.target.value)} />
  14. </label>
  15. <button type="submit">Submit</button>
  16. </form>
  17. {
  18. data && (
  19. <pre>{data.zipcode}</pre>
  20. )
  21. }
  22. </div>
  23. )
  24. }
  25. export default ZipCode;
英文:

You can't call hooks conditionally, but you can disable the query and then use its refetch to fire it when the user clicks the button.

  1. const ZipCode: NextPage = () =&gt; {
  2. const [zipcode, setZipCode] = useState(&quot;&quot;);
  3. const { data, refetch } = api.zipcode.postZipCode.useQuery({userId: &quot;1&quot;, zipcode: zipcode}, {
  4. enabled: false
  5. });
  6. const handleSubmit = () =&gt; {
  7. refetch();
  8. }
  9. return (
  10. &lt;div className=&quot;bg-[#3276AE] flex flex-col items-center h-screen&quot;&gt;
  11. &lt;form onSubmit={handleSubmit}&gt;
  12. &lt;label htmlFor=&quot;zipcode&quot;&gt;Enter your zipcode:
  13. &lt;input type=&quot;text&quot; id=&quot;zipcode&quot; name=&quot;zipcode&quot; required value={zipcode} onChange={e =&gt; setZipCode(e.target.value)} /&gt;
  14. &lt;/label&gt;
  15. &lt;button type=&quot;submit&quot;&gt;Submit&lt;/button&gt;
  16. &lt;/form&gt;
  17. {
  18. data &amp;&amp; (
  19. &lt;pre&gt;{data.zipcode}&lt;/pre&gt;
  20. )
  21. }
  22. &lt;/div&gt;
  23. )
  24. }
  25. export default ZipCode;

huangapple
  • 本文由 发表于 2023年2月6日 02:52:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75354721.html
匿名

发表评论

匿名网友

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

确定