您在一个已经传递给croeTOROOT()的容器上调用reactdomclient.createroot()

发布于 2025-01-19 20:20:36 字数 1448 浏览 3 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

孤君无依 2025-01-26 20:20:36

这也发生在我身上。对我来说,这是因为 DOMContentLoaded 回调触发了两次。

我的修复只是确保容器仅渲染一次。

let container = null;

document.addEventListener('DOMContentLoaded', function(event) {
  if (!container) {
    container = document.getElementById('root1') as HTMLElement;
    const root = createRoot(container)
    root.render(
      <React.StrictMode>
        <h1>ZOO</h1>
      </React.StrictMode>
    );
  }
});

It also happen to me. For me, it because DOMContentLoaded callback triggered twice.

My fix just make sure the container rendered only once.

let container = null;

document.addEventListener('DOMContentLoaded', function(event) {
  if (!container) {
    container = document.getElementById('root1') as HTMLElement;
    const root = createRoot(container)
    root.render(
      <React.StrictMode>
        <h1>ZOO</h1>
      </React.StrictMode>
    );
  }
});
初吻给了烟 2025-01-26 20:20:36

您可能从入口点文件导入某些内容,导致入口点文件以某种方式运行两次。我遇到了同样的问题,并通过确保没有从入口点文件导入任何内容来解决它。

You're likely importing something from your entrypoint file, causing the entry point file to somehow run twice. I've had the same issue and solved it by making sure I was not importing anything from my entrypoint file.

烟─花易冷 2025-01-26 20:20:36

在使用'react-router-dom'软件包时,可能会有其他人遇到与我相同的错误。

删除&lt; app/&gt;(或主组件)组件,然后调用&lt; routerProvider/&gt; 组件.render()功能。这样:

ReactDOM.createRoot(document.getElementById('root')).render(<App />)

应该将问题替换为

ReactDOM.createRoot(document.getElementById('root')).render(<RouterProvider router={mainRouter} />)

当您调用&lt; routerProvider&gt;.createroot时, 问题。为了解决此问题,而不是直接呈现&lt; routerProvider&gt;组件,而是应该导入并调用&lt; app&gt;&lt; routerprovider&gt; <<<< /代码>要解决此问题的组件。

routerProvider docs

There may be others who encounter the same error as I do while using the 'react-router-dom' package.

Remove the <App /> (or main component) component and instead call the <RouterProvider /> component inside the .render() function. Like this:

ReactDOM.createRoot(document.getElementById('root')).render(<App />)

should be replaced with

ReactDOM.createRoot(document.getElementById('root')).render(<RouterProvider router={mainRouter} />)

The issue arises when you invoke both <RouterProvider> and .createRoot on the same page. To resolve this problem, instead of directly rendering the <RouterProvider> component, you should import and invoke either the <App> or <RouterProvider> component to address this issue.

RouterProvider Docs

猛虎独行 2025-01-26 20:20:36

触发此警告的典型方法是在同一根部多次调用createroot

ReactDOM.createRoot(document.querySelector("#app"))
  .render(<p>A</p>);
ReactDOM.createRoot(document.querySelector("#app"))
  .render(<p>B</p>);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

您可以看到b渲染覆盖a渲染。

如果要运行两个不同的React应用程序,请使用不同的根:

ReactDOM.createRoot(document.querySelector("#app-a"))
  .render(<p>A</p>);
ReactDOM.createRoot(document.querySelector("#app-b"))
  .render(<p>B</p>);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app-a"></div>
<div id="app-b"></div>

否则,如果您试图在同一应用中渲染不同的组件,请使用单个根部组件渲染一次,并在根的子树中渲染子组件。这是常见的情况;大多数页面都使用一个React应用程序。

在大多数情况下,createroot是正面的,一次为整个React应用程序设置,该应用程序在用户访问页面的过程中持续存在。渲染条件进入组件树内部,并且要在组件中指定要呈现的元素为JSX。

例如:

const A = () => <p>A</p>;
const B = () => <p>B</p>;
const App = () => <React.Fragment><A /><B /></React.Fragment>;

ReactDOM.createRoot(document.querySelector("#app"))
  .render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

如果出于某种原因,您想多次渲染到该根部,只要您将自己限制在一个croteroot call 每个root:

const root = ReactDOM.createRoot(document.querySelector("#app"));
root.render(<p>A</p>);

// silly example
setTimeout(() => root.render(<p>B</p>), 2000);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

另一种可能性是您正在寻找一个门户,该门户可让您逃脱反应dom树并在其他地方渲染一个组件。但是,如上所述,有一个creatoot和一个Render,我们使用门户将组件放在Specfic元素中。

例如:

const A = () => <p>A</p>;
const B = () => ReactDOM.createPortal(
  <p>B</p>,
  document.querySelector("#portal")
);
const App = () => <React.Fragment><A /><B /></React.Fragment>;

ReactDOM.createRoot(document.querySelector("#app"))
  .render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>
<div id="portal"></div>

门户经常以模态看到。


为了完整性,触发这种情况的另一种罕见方法是将Babel包括两次,就像在具有babel:true的堆栈片段中可能发生的那样:

ReactDOM.createRoot(document.querySelector("#app"))
  .render(<p>test</p>);
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

这与以下方式或多或少相同:

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>
<script type="text/babel">
ReactDOM.createRoot(document.querySelector("#app"))
  .render(<p>test</p>);
</script>

The typical way to trigger this warning is to call createRoot multiple times on the same root:

ReactDOM.createRoot(document.querySelector("#app"))
  .render(<p>A</p>);
ReactDOM.createRoot(document.querySelector("#app"))
  .render(<p>B</p>);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

You can see that the B render overwrites the A render.

If you want to run two different React apps, use different roots:

ReactDOM.createRoot(document.querySelector("#app-a"))
  .render(<p>A</p>);
ReactDOM.createRoot(document.querySelector("#app-b"))
  .render(<p>B</p>);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app-a"></div>
<div id="app-b"></div>

Otherwise, if you're trying to render different components in the same app, render once with a single root component and render child components inside the root's subtree. This is the common case; most pages use one React app.

In most cases, createRoot acts as an up front, one time set up for the whole React app that persists for the duration of the user's visit to the page. Rendering conditions go inside the component tree, and the element you want to render in is specified in the component as JSX.

For example:

const A = () => <p>A</p>;
const B = () => <p>B</p>;
const App = () => <React.Fragment><A /><B /></React.Fragment>;

ReactDOM.createRoot(document.querySelector("#app"))
  .render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

If, for some reason, you want to render into that root multiple times, you can, as long as you limit yourself to one createRoot call per root:

const root = ReactDOM.createRoot(document.querySelector("#app"));
root.render(<p>A</p>);

// silly example
setTimeout(() => root.render(<p>B</p>), 2000);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

Another possibility is you're looking for a portal that lets you escape the React DOM tree and render a component elsewhere. As above, though, there's stll one createRoot and one render and we use portals to put the component in a specfic element.

For example:

const A = () => <p>A</p>;
const B = () => ReactDOM.createPortal(
  <p>B</p>,
  document.querySelector("#portal")
);
const App = () => <React.Fragment><A /><B /></React.Fragment>;

ReactDOM.createRoot(document.querySelector("#app"))
  .render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>
<div id="portal"></div>

Portals are often seen in modals.


For completeness, another uncommon way to trigger this is by including Babel twice, as can occur in a Stack Snippet that has babel: true as well as an import:

ReactDOM.createRoot(document.querySelector("#app"))
  .render(<p>test</p>);
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

Which is more or less the same as:

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>
<script type="text/babel">
ReactDOM.createRoot(document.querySelector("#app"))
  .render(<p>test</p>);
</script>

小情绪 2025-01-26 20:20:36

我遇到了这个问题,我正在使用 Rollup 捆绑一个复杂的 NPM 包,该包与我们的 Storybook 应用程序和 Create-React-App 演示页面位于同一目录中。

事实证明,我们正在捆绑 Create-React-App index.js 文件,其中已经包含 createRoot() 。这意味着它试图将包中的 React 应用程序与我们的 React 应用程序一起附加。

我通过不捆绑我们用来演示组件的 index.js 文件来解决这个问题,并制作了一个不包含 createRoot() 的“package-index.js”文件,专门用于该包。

希望这对某人有帮助:)

I had this issue, i was using Rollup to bundle a complicated NPM package that was in the same directory as our Storybook app AND Create-React-App demo page.

It turned out we were bundling the Create-React-App index.js file, which contained createRoot() already. This means it was trying to attach the react app from the package along with our react app.

I solved this by NOT bundling the index.js file that we were using to demo our components and made a 'package-index.js' file that did not contain createRoot(), specifically for the package.

Hope this helps someone :)

寄离 2025-01-26 20:20:36

我也有类似的情况,我必须在当前组件中单击按钮上呈现另一个组件。我能够通过遵循代码成功实现这一目标。

import React  from "react";
import  ReactDOM  from "react-dom/client";
import reportWebVitals from "./reportWebVitals"; 

class Lifecycle extends React.Component{ 
  showReports=()=>{  
    root.render(<Reports></Reports>);    
  }
  render() {
    return (
      <div>
        <h2>Welcome to Component Lifecycle..</h2>        
        <button onClick={this.showReports}>Show Reports</button>
        </div>
      );
    }
}

class Report extends React.Component{ 
  
  render() {
    return (
      <div>
        <h2>Welcome to Report Component..</h2>                
        </div>
      );
    }
}


const element=<Lifecycle></Lifecycle>;
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(element);
reportWebVitals();

I had the similar scenario,I had to render the another component on button click from current component. I was able to achieve this successfully by following code.

import React  from "react";
import  ReactDOM  from "react-dom/client";
import reportWebVitals from "./reportWebVitals"; 

class Lifecycle extends React.Component{ 
  showReports=()=>{  
    root.render(<Reports></Reports>);    
  }
  render() {
    return (
      <div>
        <h2>Welcome to Component Lifecycle..</h2>        
        <button onClick={this.showReports}>Show Reports</button>
        </div>
      );
    }
}

class Report extends React.Component{ 
  
  render() {
    return (
      <div>
        <h2>Welcome to Report Component..</h2>                
        </div>
      );
    }
}


const element=<Lifecycle></Lifecycle>;
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(element);
reportWebVitals();
合约呢 2025-01-26 20:20:36

我通过一个愚蠢的错误解决了旧参数:

const root = createRoot(childDomElement);
root.render(
  <React.StrictMode>
   <App />
  </React.StrictMode>,
  document.getElementById('root'),
);

最后一个不应该在那里document.getElementById('root'),

I solved it by a foolish mistake having the old parameter still there:

const root = createRoot(childDomElement);
root.render(
  <React.StrictMode>
   <App />
  </React.StrictMode>,
  document.getElementById('root'),
);

The last one should not be there document.getElementById('root'),

又爬满兰若 2025-01-26 20:20:36

答案就在警告本身中。

您正在一个容器上调用ReactDOMClient.createRoot(),该容器具有
之前已经传递给createRoot()。

我最后出现警告的根本原因是同一个 DOM 元素多次用于创建根。

为了解决这个问题,需要确保在一个 DOM 元素上仅调用 createRoot 一次,然后 root.render(reactElement); > 可用于更新,并且不应使用 createRoot

The answer is inside the warning itself.

You are calling ReactDOMClient.createRoot() on a container that has
already been passed to createRoot() before.

The root cause of the warning at my end is that the same DOM element is used to create the root more than once.

To overcome the issue it is to be sure that the createRoot is called only once on one DOM element and after that root.render(reactElement); can be used to update and createRoot should not be used.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文