React Hooks中isLoading加载状态对应UI出现两次渲染问题
问题描述
我有一个isLoading的useState变量,测试时故意注释了setIsLoading(false)语句来强制展示加载UI,却发现加载UI渲染了两次,有人知道是什么原因吗?
API调用代码
export default function App() { const [upcoming, setUpcoming] = useState([]); const [isLoading, setIsLoading] = useState(false); useEffect(() => { const fetchUpcoming = async () => { setIsLoading(true); const res = await fetch( "https://api.themoviedb.org/3/movie/upcoming?api_key={API_KEY}&language=en-US&page=1" ); const data = await res.json(); const results = data.results; setUpcoming(results); // setIsLoading(false); }; fetchUpcoming(); }, []); return ( <div className="App"> <Recommendations title={"Upcoming"} data={upcoming} loading={isLoading} /> </div> ); }
渲染结果组件代码
export default function Recommendations({ title, data, loading }) { return ( <div className="recommendationSection"> <h3>{title}</h3> {loading ? ( <h3>Loading...</h3> ) : ( data.map((movie) => { return ( <div className="banner" key={movie.title}> <img src={ movie.poster_path ? `https://image.tmdb.org/t/p/original/${movie.poster_path}` : "https://www.genius100visions.com/wp-content/uploads/2017/09/placeholder-vertical.jpg" } alt={movie.title} /> </div> ); }) )} </div> ); }
原因说明
- 代码本身的两次状态更新触发了两次加载UI渲染,完整流程如下:
- 组件首次渲染时,
isLoading初始值为false,不会展示加载UI - useEffect执行后先调用
setIsLoading(true),触发第一次重渲染,此时isLoading为true,第一次渲染出加载UI - 异步请求完成后调用
setUpcoming(results)更新列表数据,触发第二次重渲染,由于你注释了setIsLoading(false),isLoading仍然为true,第二次渲染出加载UI
- 组件首次渲染时,
- 如果你使用的是React 18开发环境且开启了严格模式(
<StrictMode>),还会多一轮重复执行:严格模式下会模拟「组件挂载-卸载-重新挂载」的流程来校验副作用逻辑,你的useEffect会完整执行两次,也会导致加载UI多渲染两次,这个问题在生产环境会自动消失。
临时测试方案
如果只是想测试加载UI的展示效果,可以直接把isLoading的初始值设为true,不需要走异步请求流程,也不会出现重复渲染的问题;也可以临时注释掉项目根组件外层的<StrictMode>标签,关闭开发环境的重复挂载逻辑。
内容的提问来源于stack exchange,提问作者cdt
相关产品推荐
相关产品推荐

