只在存在时处理查询参数,并在此之前避免显示页面的某些部分。

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

Processing query parameters only if they exist and avoid showing some part of the page until then

问题

以下是翻译好的代码部分:

const Register = () => {
    const router = useRouter()

    const { register, isLoading } = useAuth({
        middleware: 'guest',
        redirectIfAuthenticated: '/dashboard',
    })

    const [inviteToken, setInviteToken] = useState('')
    const [loading, setLoading] = useState(false)
    const [errors, setErrors] = useState([])

    const submitForm = async event => {
        event.preventDefault()

        setLoading(true)

        try {
            await register({
                first_name: firstName,
                last_name: lastName,
            })
        } finally {
            setLoading(false)
        }
    }

    useEffect(() => {
        if (router.query.token?.length > 0 && errors.length === 0) {
            setInviteToken(router.query.token)
        }
    })

    if (router.query.token?.length > 0 && errors.length === 0 && inviteToken) {
        const { data: inviteData, error: inviteError } = useSWR('/api/retrieve-invite/' + router.query.token, () => 
            axios.get('/api/retrieve-invite/' + router.query.token)
                .then(response => response.data.data)
        )

        if (!inviteData) {
            return (<PageLoader />)
        }
    }

    if (isLoading) {
        return (<PageLoader />)
    }


    return (
        // 渲染部分
    )
}

export default Register

希望这能帮助您解决问题。

英文:

I have a Next.js registration form, which allows standard registration into the application. I also use this registration form to process invitations... The url for the standard registration form is http://localhost/register. But if there is an invitation, then the url is appended with an invite token like so: http://localhost/register?token=afasdaqqeefef3d.

What I am trying to do is check to see if the token exists, if it doesn't, then just display the standard registration form, but if there is a token present, it needs to send a request to see if the token is valid, if it is valid, prefill the email field with the invitation email address, but if it isn't valid, then display a message saying that the token is invalid.

The issue I'm having is that I can't seem to contact the API and retrieve the invite details in time when I load the page with a token, it displays the normal register form until it gets the data back from the api, and then the page changes.

I do have a page loader that displays a loading spinner, but it's just not working properly.

The code I currently have is as follows:

const Register = () =&gt; {
const router = useRouter()
const { register, isLoading } = useAuth({
middleware: &#39;guest&#39;,
redirectIfAuthenticated: &#39;/dashboard&#39;,
})
const [inviteToken, setInviteToken] = useState(&#39;&#39;)
const [loading, setLoading] = useState(false)
const [errors, setErrors] = useState([])
const submitForm = async event =&gt; {
event.preventDefault()
setLoading(true)
try {
await register({
first_name: firstName,
last_name: lastName,
})
} finally {
setLoading(false)
}
}
useEffect(() =&gt; {
if (router.query.token?.length &gt; 0 &amp;&amp; errors.length === 0) {
setInviteToken(router.query.token)
}
})
if (router.query.token?.length &gt; 0 &amp;&amp; errors.length === 0 &amp;&amp; inviteToken) {
const { data: inviteData, error: inviteError } = useSWR(&#39;/api/retrieve-invite/&#39; + router.query.token, () =&gt; 
axios.get(&#39;/api/retrieve-invite/&#39; + router.query.token)
.then(response =&gt; response.data.data)
)
if (! inviteData) {
return (&lt;PageLoader /&gt;)
}
}
if (isLoading) {
return (&lt;PageLoader /&gt;)
}
return (
// rendering here
)
}
export default Register

The error I keep getting is as follows;

Error: Rendered more hooks than during the previous render.

答案1

得分: 1

你不能在if语句中调用useSWR(一个React钩子),因为这将违反Hooks规则。这就是为什么你会收到"在上一个渲染期间渲染了更多的钩子"错误的原因。你可以根据这里的说明来有条件地调用useSWR

说到这里,下面是一种实现你所寻找行为的方法(注意我如何简化了整体逻辑,使用了useRouterisReady属性):

const Register = () => {
  const {
    query: { token },
    isReady,
  } = useRouter();

  const { register, isLoading } = useAuth({
    middleware: "guest",
    redirectIfAuthenticated: "/dashboard",
  });

  // 其他钩子调用...

  const {
    data: inviteData,
    error: inviteError,
    isLoading: loadingInviteData,
  } = useSWR(isReady && token ? "/api/retrieve-invite/" + token : null, () =>
    axios.get("/api/retrieve-invite/" + token).then((response) => response.data.data)
  );

  const submitForm = async (event) => {
    //....
  };

  if (isLoading || !isReady || loadingInviteData) {
    return <PageLoader />;
  }

  return "....";
};

export default Register;
英文:

You cannot call useSWR (a React hook) in an if statement, as you will be violating the Rules of Hooks. The reason why you are getting that "Rendered more hooks than during the previous render" error. You can call useSWR conditionally as explained here.

That has been said, find below a way to implement the behavior you looking for (notice how I simplified the overall logic, using the isReady prop of useRouter):

const Register = () =&gt; {
const {
query: { token },
isReady,
} = useRouter();
const { register, isLoading } = useAuth({
middleware: &quot;guest&quot;,
redirectIfAuthenticated: &quot;/dashboard&quot;,
});
// Others hook calls...
const {
data: inviteData,
error: inviteError,
isLoading: loadingInviteData,
} = useSWR(isReady &amp;&amp; token ? &quot;/api/retrieve-invite/&quot; + token : null, () =&gt;
axios.get(&quot;/api/retrieve-invite/&quot; + token).then((response) =&gt; response.data.data)
);
const submitForm = async (event) =&gt; {
//....
};
if (isLoading || !isReady || loadingInviteData) {
return &lt;PageLoader /&gt;;
}
return &quot;....&quot;;
};
export default Register;

huangapple
  • 本文由 发表于 2023年8月5日 11:33:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76840051.html
匿名

发表评论

匿名网友

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

确定