简体   繁体   English

如何在不使用 JSX 的情况下编写 ReactJS 函数组件?

[英]How to write ReactJS function component without using JSX?

How do I write a React component as a function correctly for React Hooks ?如何为 React Hooks 正确编写 React 组件作为函数

When I attempt to write my component as a function:当我尝试将组件编写为函数时:

"use strict"

function App() {
    const [foo, setFoo] = React.useState()

    const element = React.createElement()
    return element
}

function appRender() {
    const appContainerElement = document.getElementById('app-container')
    const appComponent = App()
    ReactDOM.render(appComponent, appContainerElement)
}

The React library emits an error: React 库发出错误:

Error: Invalid hook call.错误:无效的挂钩调用。 Hooks can only be called inside of the body of a function component.钩子只能在函数组件的主体内部调用。 This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.这可能是由于以下原因之一而发生的: 1. 你可能有不匹配的 React 版本和渲染器(例如 React DOM) 2. 你可能违反了 Hooks 规则 3. 你可能有多个 React 副本同一个应用程序 请参阅https://reactjs.org/link/invalid-hook-call以获取有关如何调试和解决此问题的提示。

That component is pretty simple, it's hard to see how it fails to be a function component .该组件非常简单,很难看出它是如何失败的功能组件 The index document directly loads the React and React DOM libraries with the same version.索引文档直接加载相同版本的 React 和 React DOM 库。 I believe the component is “following the Rules of Hooks ”.我相信该组件“遵循Hooks 规则”。

Note that this is using React without JSX , as the ReactJS documentation describes.请注意,这是使用不带 JSX 的 React ,如 ReactJS 文档所述。 The React component creates an element and returns it. React 组件创建一个元素并返回它。


The index document loads the React libraries and invokes the 'appRender' function after all modules are loaded:索引文档加载 React 库并在加载所有模块后调用“appRender”函数:

<!DOCTYPE html>
<html lang="en" class="no-js">
    <head>
        <meta charset="UTF-8" />
        <script src="https://unpkg.com/react@17/umd/react.development.js"
                crossorigin></script>
        <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"
                crossorigin></script>
        <script src="/js/app.js"></script>
        <script defer>
            window.addEventListener('load', ((event) => {
                appRender()
            }))
        </script>
    </head>
    <body>
        <div id="app-container">
            <div id="app" class="initial-placeholder">
                <p class="loading-status">Preparing the app…</p>
            </div><!-- #app -->
        </div><!-- #app-container -->
    </body>
</html>

This correctly invokes the 'appRender' function.这正确调用了“appRender”函数。

What is the error?错误是什么? How do I correct this component so I can use React Hooks in it ?如何更正此组件以便我可以在其中使用 React Hooks

You are breaking this rule of hooks :你正在打破这个钩子规则

Only Call Hooks from React Functions只从 React 函数调用钩子

What makes a function a "react" function is that it's called synchronously as react is rendering.使函数成为“反应”函数的原因是它在反应渲染时被同步调用。 So directly executing your function like App() executes your functional component, but react is not currently rendering.所以像App()这样直接执行你的函数会执行你的功能组件,但是 react 当前没有渲染。 So you get an error because there is no current react context for the hooks to "hook" into.所以你会得到一个错误,因为当前没有钩子可以“挂钩”到的反应上下文。

To solve this you need to either execute your component as JSX, which does the magic for you:要解决这个问题,您需要将您的组件作为 JSX 来执行,这对您来说很神奇:

ReactDOM.render(<App />, appContainerElement)

Or if you really want to avoid JSX at all costs, then do it manually:或者,如果你真的想不惜一切代价避免 JSX,那么手动执行:

const appComponent = React.createElement(App)
ReactDOM.render(appComponent, appContainerElement)

Either way you have to tell React to render your component.无论哪种方式,您都必须告诉 React 渲染您的组件。 The component is not smart enough to completely render itself in this way.该组件不够智能,无法以这种方式完全呈现自身。

Working example on stack blitz堆栈闪电战的工作示例

Instead of manually calling your App function you need to pass your component to React and let react invoke your function.您需要将组件传递给 React 并让 react 调用您的函数,而不是手动调用您的 App 函数。

Instead of:代替:

const appComponent = App()
ReactDOM.render(appComponent, appContainerElement)

Try:尝试:

const reactElement = React.createElement(App, {}, null);
ReactDOM.render(reactElement, appContainerElement)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM