钩子必须总是以完全相同的顺序被调用完全相同的次数。这是必要的,因为例如,如果您多次调用
useState
,react必须依赖于调用的顺序来确定应该从的哪个调用返回哪个状态
使用状态
.
See rules of hooks
.
至于如何解决这个问题,有几种可能性:
-
在您的示例中,您的自定义钩子实际上并不调用任何其他钩子。如果真正的代码也是如此,那么你就会得到一个错误的警报。lint规则使用命名约定来识别什么是钩子,什么不是钩子,函数以
use
被假定为钩子。要解决此问题,请重命名该函数。如,
function getNameProps(
。但既然我知道你省略了代码,我想可能是吧
做
需要成为一个钩子,所以这个解决方案不适合你。
-
如果它不贵,那么每次都打电话给它。你说的
是
昂贵,所以这个解决方案不适合您,但我包括它,因为它是这个错误消息的最常见的解决方案(因为大多数钩子都是轻量级的)
export default function ComposeBottom() {
const nameProps = useNameProps('Frank', 'Lee');
return <div>{showShowName() && <Name {...nameProps} />}</div>;
}
-
修改
useNameProps
所以你可以把一些东西传给它,告诉它不要做昂贵的计算。例如,也许路过
null
可以告诉它什么都不做。您仍然需要调用任何钩子相同的次数,但您可以跳过其余的。
function useNameProps(options: UseNameOptions | null): NameProps | null {
// If there are any hooks you are calling, they must be before you bail out
const [foo, setFoo] = useState('bar')
useEffect(() => {
//...
}, [])
if (options === null) {
return null;
}
// else, do expensive stuff
}
export default function ComposeBottom() {
const nameProps = useNameProps('Frank', 'Lee');
return <div>{showShowName() && <Name {...nameProps} />}</div>;
}
-
移动的用法
useNameProps
到子组件中,并且在不需要时不要渲染该组件。
export default function ComposeBottom() {
return <div>{showShowName() && <Child />}</div>;
}
function Child() {
return <Name {...useNameProps('Frank', 'Lee')} />
}