如何避免Suspense与use结合时React子组件重复渲染?
解决React组件重复渲染导致Promise重复创建的问题
你的问题核心是:父组件App的状态更新触发重渲染时,FirstChild随之重新执行并创建新的Promise,导致Suspense再次进入加载状态。按照React“同位置组件保留状态”的规则,可以通过以下两种方式解决:
方案一:用useMemo缓存Promise实例
通过useMemo将Promise的创建逻辑缓存起来,确保组件重渲染时复用同一个Promise,避免重复触发Suspense挂起。
修改后的代码:
import { Suspense, use, useState, useMemo } from 'react' function FirstChild({ setSecondContent }) { // 用useMemo缓存Promise,仅在依赖项变化时重新创建 const promise = useMemo(() => new Promise(resolve => { setTimeout(() => { setSecondContent('More content...'); resolve('Done!'); }, 3000); }), [setSecondContent]); // useState返回的setter引用稳定,不会触发重新创建 return ( <Suspense fallback={<>{'Loading...'}<br/></>}> <FirstChildContent contentPromise={promise} /> </Suspense> ); } function FirstChildContent({ contentPromise }) { const content = use(contentPromise); return <>{content}<br/></>; } function SecondChild({ content }) { return content; } export default function App() { const [secondContent, setSecondContent] = useState(''); return ( <> <FirstChild setSecondContent={setSecondContent} /> { secondContent !== '' && <SecondChild content={secondContent} /> } </> ); }
方案二:用React.memo避免不必要的重渲染
React.memo会对组件的props做浅比较,当props未发生变化时,跳过组件的重渲染,从根源上避免Promise重复创建。
修改后的代码:
import { Suspense, use, useState, memo } from 'react' // 用memo包裹FirstChild,props未变化时不触发重渲染 const FirstChild = memo(function({ setSecondContent }) { const promise = new Promise(resolve => { setTimeout(() => { setSecondContent('More content...'); resolve('Done!'); }, 3000); }); return ( <Suspense fallback={<>{'Loading...'}<br/></>}> <FirstChildContent contentPromise={promise} /> </Suspense> ); }); function FirstChildContent({ contentPromise }) { const content = use(contentPromise); return <>{content}<br/></>; } function SecondChild({ content }) { return content; } export default function App() { const [secondContent, setSecondContent] = useState(''); return ( <> <FirstChild setSecondContent={setSecondContent} /> { secondContent !== '' && <SecondChild content={secondContent} /> } </> ); }
核心逻辑说明
两种方案本质都是遵循React“同位置组件保留状态”的规则:
- 方案一通过缓存Promise,让组件重渲染时复用原有异步资源,避免重复挂起;
- 方案二通过阻止不必要的重渲染,确保Promise只在组件初次挂载时创建一次。
内容的提问来源于stack exchange,提问作者pdacostaporto
相关产品推荐
相关产品推荐

