英文:
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 = () => {
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 (
// 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
。
说到这里,下面是一种实现你所寻找行为的方法(注意我如何简化了整体逻辑,使用了useRouter
的isReady
属性):
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 = () => {
const {
query: { token },
isReady,
} = useRouter();
const { register, isLoading } = useAuth({
middleware: "guest",
redirectIfAuthenticated: "/dashboard",
});
// Others hook calls...
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;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论