微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用单个加载器动画反应路由器预加载来自多个组件的数据

如何解决使用单个加载器动画反应路由器预加载来自多个组件的数据

我有一个应用需要具有动态标头,从提取请求加载外部文件

一旦用户登录,他们就会被定向到门户 /portal。我已将布局定义为:

export const UserLayout = ({ children }) => <div><Header /><div className="body">{children}</div></div>

包括一个包含动态链接的标头,然后允许传递路由,因此不会在每次页面更改时加载标头。

export const UserRoutes = () => {
  return (
    <UserLayout>
      <Switch> 
        <Route path="/portal" exact component={Portal}/>
        <Route path="/settings" exact component={Settings}/>
      </Switch>
    </UserLayout>
  );
}

头从 /login 重定向/portal 后首先加载。 我在 redux 中设置了一个全局加载器,它基本上在获取数据时显示全屏加载动画。

我遇到的主要问题是,如何在一个请求中加载应用程序的两个部分?

比如header加载ajax内容显示redux加载动画,然后停止。然后路由加载,它也显示一个 redux 加载动画,然后停止。这会产生闪烁效果

同时拥有主要部分负载和子负载的最佳方法是什么?

解决方法

我不知道你的应用是如何构建的,但这会给你一个想法。您可以向 state 添加属性以控制待处理的请求。

const STATE = {
 requests: []
 ...
}

定义基本的 actions(您可以添加更多,例如请求取消等)。您需要知道请求何时开始以及何时结束:

const requestStartedAction = id => ({
  type: REQUEST_STARTED,payload: { id } //--> something to identify the request
});

const requestEndedAction = id => ({
  type: REQUEST_ENDED,payload: { id }
});

reducer

export default function(state = {},action) {
  switch (action.type) {
    case REQUEST_STARTED:
      return {
        ...state,requests: [...state.requests,action.payload.id],//-> add a new request to the list
        loading: true,};
    case REQUEST_ENDED:
      const pendingRequests = state.requests.filter(id => id!== action.payload.id); //--> remove request from the list
      return {
        ...state,requests: pendingRequests,loading: !Boolean(pendingRequests.length),//--> don't hide the loading if there any request pending
       
      };
    
   ...
  }
}

然后,每次您发出请求时,您都会调用 requestStartedAction。当请求完成时,您可以调用 requestEndedAction。使用 fetch 的基本示例:

dispatch(requestStartedAction(ID));
fetch(URL).finally(() => dispatch(requestEndedAction(ID)));

如果请求列表为空,加载效果将停止。

,

你不需要任何 redux...

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

import Loader from './path/to/loader'

const Component1 = lazy(() => import('./path/to/component1')
const Component2 = lazy(() => import('./path/to/component2')

const Router = () => {
  <Suspense fallback={<Loader/>}>
    <BrowserRouter>
      <Switch>
        <Route path='/path1' component={Component1}/>
        <Route path='/path2' component={Component2}/>
      </Switch>
    </BrowserRouter>
  </Suspense>
}

如果这对您不起作用,那么您需要创建一个父级,该父级可以在呈现之前获取所需的所有数据并将其传递给子级,然后您可以在该父级中显示加载器。

如果您让全局组件在每次进行 fetch 调用时管理加载,您最终将始终处理闪烁或双重加载级联效应。

,

here is the project with redux and a single loading

我做了一个加载减速器,在每个组件中如果需要获取数据,start-loading 被分派并将一个值推入加载数组,当数据被获取时,stop-loadig 被分派并赋值从数组中弹出。

const LoadingReducer = (state = initState,action) => {
  const prevState = { ...state };
  switch (action.type) {
    case "START_LOADING":
      prevState.loading.push(true);
      return { ...state,prevState };
    case "STOP_LOADING":
      prevState.loading.pop(true);
      return { ...state,prevState };
    default:
      return state;
  }
};

App.js 中,我只是从商店获取加载并检查它是否有价值,然后决定是否显示 Loader

import { useEffect,useState } from "react";
import { connect } from "react-redux";
import UserRoutes from "./UserRoutes";
import Loader from "./Loader";
import "./styles.css";

const App = (props) => {
  const [loading,setLoading] = useState(0);
  useEffect(() => {
    setLoading(props.loading);
  },[props.loading]);
  return (
    <div className="App">
      {loading && <Loader />}
      <UserRoutes />
    </div>
  );
};
const mapStateToProps = (state) => {
  return {
    loading: state.LoadingReducer.loading.length > 0 ? true : false
  };
};

export default connect(mapStateToProps,null)(App);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。