You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS:如何在函数组件渲染前修改Redux状态以显示Loading?

React+Redux 全局Loading组件控制方案

问题场景

我有一个<Loading />组件,它包裹了应用中的所有路由。该组件通过isLoading属性接收Redux状态变量,以此控制自身的显示隐藏。当前代码如下:

function App() {
    const isLoading = useSelector((state) => state.loading.value)
    
    return (
        <Loading isLoading={isLoading}>
            <BrowserRouter>
                <Routes>
                    <Route path='/' element={<Hypertube />} />
                    <Route path='/login' element={<Login />} />
                    <Route path='/register' element={<Register />} />
                </Routes>
            </BrowserRouter>
        </Loading>
    );
}

需求是:用户打开页面时,自动将Redux状态设为true显示Loading,页面渲染完成后再隐藏。原本想用已废弃的componentWillMount(),现在需要替代方案。我自己想到一个不太满意的方法:

  • 将Redux状态默认值设为true,实现首次加载显示
  • 路由跳转时手动把状态改成true

更优解决方案

1. 处理首次加载的显示与隐藏

使用useEffect钩子在组件挂载时初始化加载状态,然后监听页面加载完成事件(或组件渲染完成)来关闭Loading:

import { useDispatch, useSelector } from 'react-redux';
import { useEffect } from 'react';

function App() {
    const isLoading = useSelector((state) => state.loading.value);
    const dispatch = useDispatch();

    useEffect(() => {
        // 组件挂载时立即开启加载状态
        dispatch(setLoading(true));
        
        // 监听页面所有资源(图片、脚本等)加载完成
        const handlePageLoad = () => {
            dispatch(setLoading(false));
        };

        window.addEventListener('load', handlePageLoad);

        // 组件卸载时清理监听
        return () => {
            window.removeEventListener('load', handlePageLoad);
        };
    }, [dispatch]);

    return (
        <Loading isLoading={isLoading}>
            <BrowserRouter>
                <Routes>
                    <Route path='/' element={<Hypertube />} />
                    <Route path='/login' element={<Login />} />
                    <Route path='/register' element={<Register />} />
                </Routes>
            </BrowserRouter>
        </Loading>
    );
}

如果不需要等待图片等资源,只需要组件渲染完成即可关闭Loading,改用setTimeout(利用宏任务特性,确保组件已渲染):

useEffect(() => {
    dispatch(setLoading(true));
    // 等待组件渲染完成后关闭
    const timer = setTimeout(() => {
        dispatch(setLoading(false));
    }, 0);

    return () => clearTimeout(timer);
}, [dispatch]);

2. 处理路由跳转时的加载状态

通过useLocation监听路由变化,触发加载状态:

import { useDispatch, useSelector } from 'react-redux';
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

function App() {
    const isLoading = useSelector((state) => state.loading.value);
    const dispatch = useDispatch();
    const location = useLocation();

    // 路由变化时触发加载
    useEffect(() => {
        dispatch(setLoading(true));
        // 可根据实际页面加载时间调整延迟
        const timer = setTimeout(() => {
            dispatch(setLoading(false));
        }, 300);

        return () => clearTimeout(timer);
    }, [location.pathname, dispatch]);

    // 首次加载逻辑
    useEffect(() => {
        dispatch(setLoading(true));
        window.addEventListener('load', () => dispatch(setLoading(false)));
        return () => window.removeEventListener('load', () => dispatch(setLoading(false)));
    }, [dispatch]);

    return (
        <Loading isLoading={isLoading}>
            <BrowserRouter>
                <Routes>
                    <Route path='/' element={<Hypertube />} />
                    <Route path='/login' element={<Login />} />
                    <Route path='/register' element={<Register />} />
                </Routes>
            </BrowserRouter>
        </Loading>
    );
}

懒加载组件的简化方案

如果你的路由组件是懒加载的,直接用React原生的Suspense组件,无需手动管理Redux状态:

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { Suspense, lazy } from 'react';

// 懒加载路由组件
const Hypertube = lazy(() => import('./Hypertube'));
const Login = lazy(() => import('./Login'));
const Register = lazy(() => import('./Register'));

function App() {
    return (
        <BrowserRouter>
            {/* 组件加载完成前显示Loading */}
            <Suspense fallback={<Loading isLoading={true} />}>
                <Routes>
                    <Route path='/' element={<Hypertube />} />
                    <Route path='/login' element={<Login />} />
                    <Route path='/register' element={<Register />} />
                </Routes>
            </Suspense>
        </BrowserRouter>
    );
}

这种方式下,React会自动处理组件加载过程中的状态,代码更简洁。

内容的提问来源于stack exchange,提问作者arrmani88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 17:50:35