<Suspense> 作为根元素会导致生产和开发中出现组件的两个实例(无 <StrictMode>)

Jor*_*n L 6 reactjs

注意:这种情况在开发和生产中都会发生,但我<StrictMode>根本没有使用。

看起来工作正常:

B.js

export default function B()
{
    return <p>B</p>
}
Run Code Online (Sandbox Code Playgroud)

测试应用程序.js

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>
}
Run Code Online (Sandbox Code Playgroud)

索引.js

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>);
Run Code Online (Sandbox Code Playgroud)

<Suspense>但是当组件树中有一个更深层次的组件时(在 TestApp 本身中, suspending <B>),<TestApp>就会出现重复。

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

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

要查看该问题,请转到演示并打开控制台,您将看到“rendering TestApp - counter 1”两次。如果这只是双重渲染,我预计计数器会增加。

我对反应还很陌生,并且非常清楚我可能做错了什么,但任何信息将不胜感激。

提前致谢!

Jon*_*ski 6

您的应用程序没有不必要的重新渲染;这就是 React 和闭包的工作原理。

正如所解释的,应用程序首先加载 Suspense 组件,一旦延迟加载完成,就会渲染 TestApp 组件。

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