React - 比之前的渲染期间渲染了更多的钩子(有条件地)

问题描述 投票:0回答:2

我知道这个错误已经出现过很多次了:

渲染了比之前渲染更多的钩子。

据我所知,这与提前退货声明有关。好吧,我正在为我们公司创建一个库,我在其中包装一个表单并允许他们传递自己的布局。最初,表单尚未准备好呈现其表单(取决于几个因素),但最终它已准备好并且应该呈现。这会创建一个条件渲染,并返回该错误。

我不明白的是,如果我显式检查布尔值以确定它是否已准备好,我不会渲染任何存在无效数量的钩子的内容。

我创建了下面问题/错误的简化示例。在这里,我检查它是否“准备好”(是的,我只是在 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>
reactjs react-redux jsx
2个回答
0
投票

我错过了一些简单的事情吗?

是的。如果

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} />


0
投票

当您将组件作为普通函数调用时

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>
© www.soinside.com 2019 - 2024. All rights reserved.