我有一个组件,它使用另一个组件作为渲染器。然而,React不允许我在渲染器组件中使用钩子,因为它会抛出以下错误:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
以下是我的显示组件中的一个示例,它是一个错误边界:
class DisplayComponent extends Component {
// ...
render() {
const { rendererComponent } = this.props;
return rendererComponent({ enabled: true, name: 'hello-world' })
}
}
正如您所看到的,DisplayComponent
中的rendererComponent
道具是作为一个函数调用的,尽管它是一个组件,并且我在这样调用它时将一些道具传递给它。
现在,在我使用DisplayComponent
的另一个文件中,它看起来像这样:
const RendererComponent = (props) => {
const { enabled, name } = props;
const [testState, setTestState] = useState(); // Error: Invalid hook call
useEffect(() => {
// Error: Invalid hook call
}, [testState]);
return (
<div>{name} - {enabled}</div>
)
}
const App = () => {
return (
<DisplayComponent rendererComponent={RendererComponent} />
)
}
这是关键。由于某些原因,我不能在RendererComponent
中使用useEffect
、useState
等钩子。如果我使用它,React会抛出我上面提到的钩子无效的错误。但是我想要一些需要RendererComponent
中钩子的逻辑。
我如何使用钩子来在一个组件中产生状态和效果,而这个组件是以我的方式调用的?
您正在进行函数调用,而不是安装组件,这是两种不同的调用和语法,请将其更改为:
class DisplayComponent extends Component {
render() {
// Custom component must be Capitalized
const { rendererComponent: RenderedComponent } = this.props;
return <RenderedComponent enabled name="hello-world" />;
}
}
// Notice that the JSX is transpiled to
React.createElement(RenderedComponent, {
enabled: true,
name: "hello-world"
});
在React中,您只能通过用React.createElement
调用其API来装载组件(JSX是其糖语法(,而简单的函数调用则是纯粹的JS,它不会触发React API,即不会将组件注册到组件树中。因此,像hook这样的内部实现没有任何意义,您将在每次渲染时丢失状态(不会触发Recommendation(。