我收到此错误“无效的钩子调用。只能在函数组件的主体内部调用钩子。”当我尝试运行我的函数时。我正在尝试运行一个生成 reCaptcha 令牌的脚本,脚本如下:
<块引用>这个组件应该生成令牌(这是我得到的地方 错误)
import * as React from 'react'
import { RECAPTCHA_KEY } from '../../../utils/env'
// @ts-ignore
declare const window: any
interface RecaptchaProps {
actionType: string
}
export const RecaptchaGen = ({ actionType }: RecaptchaProps) => {
const siteKey = RECAPTCHA_KEY
const [loaded, setLoaded] = React.useState(false)
React.useEffect(() => {
const scriptTag = document.createElement('script')
scriptTag.src = 'https://www.google.com/recaptcha/api.js?render=' + siteKey
document.appendChild(scriptTag)
return () => {
scriptTag.remove()
setLoaded(false)
}
}, [siteKey])
React.useEffect(() => {
if (!loaded) return
window.grecaptcha.ready(function () {
window.grecaptcha
.execute(siteKey, {
action: actionType,
})
.then(function (token: string) {
//reCaptch token generated needs to be sent to the back end for validation
console.log(token)
})
})
}, [loaded, actionType, siteKey])
}
<块引用>
在另一个组件中,我调用先前的脚本组件 一个动作类型通过,但我收到反应钩子错误 提到(仅显示相关代码片段)。
import * as React from 'react'
import { RecaptchaGen } from '../../../components/_molecules/Recaptcha'
const onLoginClick = () => {
RecaptchaGen({ actionType: 'login' })
}
我认为问题在于我调用/使用导入组件的方式,但我找不到解决方案?
答案 0 :(得分:1)
您在常规 useEffect
函数中使用了 js
钩子。
hooks
只能在有效的 React 组件中调用。 RepcaptchaGen
不是 React 组件,因为它不使用 React 组件特定的东西,例如返回一些 jsx
。
答案 1 :(得分:1)
名称 RecaptchaGen
表明它是构造函数或组件,但两者都不是。它是一个自定义钩子,所以应该以 use
开头,例如:useRecaptchaGen。
以下是您在组件中使用它的方法:
export const useRecaptchaGen = (action) => {
if (!action) {
return;
}
const { actionType }: RecaptchaProps = action;
//....rest of your code
};
const Component = () => {
const [action, setAction] = React.useState(false);
const onLoginClick = () => {
setAction({ actionType: 'login' });
};
//cannot conditionally call hooks
useRecaptchaGen(action);
};
答案 2 :(得分:1)
这样做的原因是您没有在 RecaptchaGen 函数中返回任何代码。 JSX 返回,除其他外,是 React Functional 组件与常规 javascript 函数的区别,常规 javascript 函数不能使用钩子。如果要解决此问题,请添加 return 语句。
答案 3 :(得分:1)
我不熟悉你的具体用例,但一个常见的模式是将一些效果逻辑封装到一个由你的自定义钩子返回的函数中,然后任何普通的JS函数(回调与否)都可以调用那个功能。
将 RecaptchaGen
重命名为 useRecaptchaGen
,以便将其用作 React 钩子。
返回一个函数来基本上替换第二个 useEffect
回调。
export const useRecaptchaGen = ({ actionType }: RecaptchaProps) => {
const siteKey = RECAPTCHA_KEY
const [loaded, setLoaded] = React.useState(false)
React.useEffect(() => {
const scriptTag = document.createElement('script')
scriptTag.src = 'https://www.google.com/recaptcha/api.js?render=' + siteKey
document.appendChild(scriptTag)
return () => {
scriptTag.remove()
setLoaded(false)
}
}, [siteKey]);
const generateRecaptcha = () => {
if (!loaded) return;
window.grecaptcha.ready(function () {
window.grecaptcha
.execute(siteKey, {
action: actionType,
})
.then(function (token: string) {
//reCaptch token generated needs to be sent to the back end for validation
console.log(token)
})
})
};
return { generateRecaptcha };
}
在组件中使用新的钩子和解构 generateRecaptcha
。
const { generateRecaptcha } = useRecaptchaGen({ actionType: 'login' });
在 generateRecaptcha
处理程序中调用 onLoginClick
。
const onLoginClick = () => {
generateRecaptcha();
}