反应中的全局屏幕加载器

Posted

技术标签:

【中文标题】反应中的全局屏幕加载器【英文标题】:Global screen loader in react 【发布时间】:2021-06-10 00:57:12 【问题描述】:

我正在寻找在 react 中使用全局屏幕加载器的解决方案。

我对反应上下文不太熟悉,但我想知道这是否可以帮助我。 基本上我正在介绍一个屏幕加载器,我在想也许最好的方法是在主要组件的某个地方有一个全局加载器。所以得出结论:

我想在主组件中有全局加载器 我想在应用中的任何地方更新全局加载器的状态 我不想用 ScreenLoaders 污染我需要使用它的所有组件 我想为它使用钩子

那么有没有办法获得 loader/loaderText 的全局状态,并在需要时使用上下文进行设置和重置?

如果有一种简单的方法可以做到这一点,那么您认为使用这种解决方案可能有什么缺点吗?也许这有点过头了。

【问题讨论】:

【参考方案1】:

如何创建一个自定义钩子useLoading,它可以用于任何可以从全局上下文访问loadingsetLoading 的组件?

// LoadingContext.js
import  createContext, useContext, useState  from "react";

const LoadingContext = createContext(
  loading: false,
  setLoading: null,
);

export function LoadingProvider( children ) 
  const [loading, setLoading] = useState(false);
  const value =  loading, setLoading ;
  return (
    <LoadingContext.Provider value=value>children</LoadingContext.Provider>
  );


export function useLoading() 
  const context = useContext(LoadingContext);
  if (!context) 
    throw new Error("useLoading must be used within LoadingProvider");
  
  return context;

// App.jsx
import  LoadingProvider  from "./LoadingContext";

function App() 
    return (
        <LoadingProvider>
            <RestOfYourApp />
       </LoadingProvider>
    );

// RestOfYourApp.js
import  useLoading  from "./LoadingContext";

function RestOfYourApp() 
    const  loading, setLoading  = useLoading();
    // ...

【讨论】:

看起来不错。谢谢。很快就会尝试一下 ts 的变种? @kakabali,我的回答部分受到这篇文章的启发,该文章有一些 TS 代码示例。不完全是这样,但它会为您指明正确的方向:kentcdodds.com/blog/how-to-use-react-context-effectively @BenStickley 非常感谢您提供的非常准确的链接 Upvoted @Watchmaker,见kentcdodds.com/blog/…【参考方案2】:

useLoader.js(钩子)

import React,  useState  from "react";
import Loader from "./loader";
const useLoader = () => 
  const [loading, setLoading] = useState(false);
  return [
    loading ? <Loader /> : null,
    () => setLoading(true),
    () => setLoading(false),
  ];
;
export default useLoader;

loader.js(加载器组件)

import React from "react";
import styled from "styled-components";
import spinner from "./loader.gif"; // create gif from https://loading.io
import Color from "../../Constant/Color";

const Loader = () => 
  return (
    <LoaderContainer>
      <LoaderImg src=spinner />
    </LoaderContainer>
  );
;


const LoaderContainer = styled.div`
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  background: $Color.greyBg;
  z-index: 100;
`;
const LoaderImg = styled.img`
  position: absolute;
`;

export default Loader;

使用 Loader 钩子

import useLoader from "../../../hooks/loader/useLoader"; /// import loader hook

const App = (props) => 
const [loader, showLoader, hideLoader] = useLoader(); //initialize useLoader hook


useEffect(() => 
    showLoader(); /// loading starts
   
    Axios.post("url")
      .then((res) => 
        hideLoader(); // loading stops
      )
      .catch((error) => 
        hideLoader();// loading stops
      );
  , []);

return (
<>
loader /// important 

//// add your elements /////
</>
)

export default App;

【讨论】:

但在这种情况下,我总是必须将loader 应用于我需要的每个组件,对吗?这就是我想要避免的。要在例如 App 组件中只有一个全局加载器 html 元素并依赖于其他组件中的某些获取 - 将加载状态设置为 true/false 为此你必须使用 redux。在你的应用程序的顶层调用这个 useLoader 钩子,例如你设置路由的地方。并渲染 loder。创建一个布尔值的redux状态,在你使用路由的地方添加使用效果钩子,只要你想showloader()将redux状态的值更改为true并将hideloader设置为false。如果你不想使用 redux,请使用 ,useContext hook。

以上是关于反应中的全局屏幕加载器的主要内容,如果未能解决你的问题,请参考以下文章

如何在本机反应中使用全局变量?

在获取 API 调用之前反应加载屏幕

反应,流星,webpack,es6。如何创建加载/启动屏幕

当我的屏幕第二次加载时,反应本机组件接收道具不加载

在反应加载屏幕中保持几个动作

使用 bloc 创建全局加载屏幕的最佳方法?