首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 ><Suspense>作为根元素会导致生产中的两个组件实例和dev (没有<StrictMode>)

<Suspense>作为根元素会导致生产中的两个组件实例和dev (没有<StrictMode>)
EN

Stack Overflow用户
提问于 2022-08-11 19:04:29
回答 2查看 210关注 0票数 6

注意:这在开发和生产中都会发生,我根本不使用<StrictMode>

它似乎工作得很好:

B.js

代码语言:javascript
运行
复制
export default function B()
{
    return <p>B</p>
}

TestApp.js

代码语言:javascript
运行
复制
import { lazy, Suspense } from "react";
const B = lazy(()=>import("./B"));

export default function TestApp()
{
    const counter = useRef(0);
    counter.current++;
    console.log("rendering TestApp - counter",counter.current);
    return <Suspense fallback={<p>loading B...</p>}><B/></Suspense>
}

index.js

代码语言:javascript
运行
复制
import { lazy, Suspense } from "react";
import {createRoot} from "react-dom/client";
const TestApp = lazy(()=>import("./TestApp"));

const root = createRoot(document.getElementById("root"));
root.render(<Suspense fallback={<p>loading testapp...</p>}><TestApp/></Suspense>);

但是,当组件树中有一个更深的<Suspense> (在TestApp本身中,挂起<B>)时,<TestApp>会被复制。

项目:https://github.com/jmlee2k/react-suspense-root

演示:https://jmlee2k.github.io/react-suspense-root/ (生产构建)

要查看问题,转到演示并打开控制台,您将看到两次“呈现TestApp计数器1”。如果这只是一个双重渲染,我希望计数器会增加.

我是相当新的反应,我很清楚我可能做错了什么,但任何信息都将不胜感激。

提前感谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-21 11:48:14

您的应用程序没有不必要的重新呈现;这是React和闭包的工作方式。

如前所述,应用程序首先加载悬念组件,并在延迟加载完成后呈现TestApp组件。

在此过程中,function装入调用该函数的TestApp组件。这里有第一个invoke count值。当B延迟加载时,将再次调用该函数。但是没有重新渲染,因为它的状态没有改变。TestApp组件中的所有变量都被刷新了,除了useRef组件。这就是为什么在组件中有尽可能少的处理程序(在每次呈现时都会刷新)是一个好主意,也是为什么在useEffect中包装代码(也称为效果)是个好主意。

票数 6
EN

Stack Overflow用户

发布于 2022-08-11 21:04:47

这与反应的方式有关。每当任何组件的状态或属性发生更改时,响应更新其虚拟DOM树。例如,在这里,您可以看到在状态发生更改时组件是如何再次呈现的。

代码语言:javascript
运行
复制
const {useState} = React;

const Example = () => {
console.log("Hi mom!I re-rendered")
    const [count, setCount] = useState(0);
  
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={() => setCount(count + 1)}>
                Click me
            </button>
        </div>
    );
};

// Render it
ReactDOM.createRoot(
    document.getElementById("root")
).render(
    <Example />
);
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
<div id="root"></div>

请记住,应用程序的流程如下:

  1. 响应加载TestApp,悬念显示了后备,因为组件B尚未加载(第一次呈现)

  1. 组件B最终加载并显示其内容。(二次渲染)

所以您的代码没有什么问题,因为这是react的自然行为,但是,如果有许多不必要的重新呈现,应用程序可能会遇到性能问题。

更新

我环顾四周,显然useRef不起作用,但我尝试了console.count,现在起作用了

代码语言:javascript
运行
复制
import { lazy, Suspense, useRef } from "react";
const B = lazy(()=>import("./B"));

export default function TestApp()
{
    console.count('counter')

    return <Suspense fallback={<p>loading B...</p>}><B/></Suspense>
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73325723

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档