我知道这个错误已经出现过很多次了:
渲染了比之前渲染更多的钩子。
据我所知,这与提前退货声明有关。好吧,我正在为我们公司创建一个库,我在其中包装一个表单并允许他们传递自己的布局。最初,表单尚未准备好呈现其表单(取决于几个因素),但最终它已准备好并且应该呈现。这会创建一个条件渲染,并返回该错误。
我不明白的是,如果我显式检查布尔值以确定它是否已准备好,我不会渲染任何存在无效数量的钩子的内容。
我创建了下面问题/错误的简化示例。在这里,我检查它是否“准备好”(是的,我只是在 useEffect 中执行此操作,但它比这更复杂,但结果是相同的)。然后,我有条件地检查我们是否准备好渲染它们的布局(可能包含也可能不包含钩子 - 这会产生错误),或者我想返回默认组件消息。
从阅读中我必须渲染这个动态组件,无论是否要传递一个 prop 给子组件,因此消费者必须检查它是否准备好然后进行布局 - 这很令人讨厌。
情况真的如此还是我错过了一些简单的事情?我可以禁用该错误,因为我知道在某个状态准备好之前这是不可能的吗?
这将产生错误:
export function ParentComponent({childComponent}) {
const [ready, setReady] = useState(false);
useEffect(() => {
console.log("Mounted, now ready");
setReady(true);
}, []);
if (ready)
// This is what a user passes, so can be any component which can use hooks, as per my example
return childComponent();
return <p>Not ready yet.</p>
}
export function childComponent() {
// Important, this breaks it
const [someStateValue, setSomeStateValue] = useState(false);
return <p>Hello: {someStateValue}</p>;
}
用途:
return <ParentComponent childComponent={childComponent}></ParentComponent>
我错过了一些简单的事情吗?
是的。如果
childComponent
是一个组件,您应该像组件一样渲染它。这样, childComponent
函数调用的任何钩子都将作为单独的组件与其关联,而不是与父组件关联。通过像普通函数一样调用它,React 没有办法告诉子组件的钩子不应该是组件的“一部分”。
export function ParentComponent({
childComponent: ChildComponent
}) {
...
if (ready) {
return <ChildComponent/>
} else {
return <p>Not ready yet.</p>
}
}
注意我对你原来的帖子进行了更改的
childComponent: ChildComponent
。我不是 100% 立即确定,但我认为这是必要的,这样 React 就不会尝试做例如一个document.createElement('childComponent')
。您仍然可以将该道具用作 <ParentComponent childComponent={childComponent} />
当您将组件作为普通函数调用时
myComponent()
,React 与将其用作 JSX(或 React.createElement(myComponent)
)不同。
您可以将其更改为使用 JSX 并将组件名称大写以允许使用钩子:
export function ParentComponent({childComponent}) {
const [ready, setReady] = useState(false);
useEffect(() => {
console.log("Mounted, now ready");
setReady(true);
}, []);
if (ready)
// This is what a user passes, so can be any component which can use hooks, as per my example
const ChildComponent = childComponent;
return <ChildComponent />
return <p>Not ready yet.</p>