反应中的全局屏幕加载器
Posted
技术标签:
【中文标题】反应中的全局屏幕加载器【英文标题】:Global screen loader in react 【发布时间】:2021-06-10 00:57:12 【问题描述】:我正在寻找在 react 中使用全局屏幕加载器的解决方案。
我对反应上下文不太熟悉,但我想知道这是否可以帮助我。 基本上我正在介绍一个屏幕加载器,我在想也许最好的方法是在主要组件的某个地方有一个全局加载器。所以得出结论:
我想在主组件中有全局加载器 我想在应用中的任何地方更新全局加载器的状态 我不想用 ScreenLoaders 污染我需要使用它的所有组件 我想为它使用钩子那么有没有办法获得 loader/loaderText 的全局状态,并在需要时使用上下文进行设置和重置?
如果有一种简单的方法可以做到这一点,那么您认为使用这种解决方案可能有什么缺点吗?也许这有点过头了。
【问题讨论】:
【参考方案1】:如何创建一个自定义钩子useLoading
,它可以用于任何可以从全局上下文访问loading
和setLoading
的组件?
// 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。以上是关于反应中的全局屏幕加载器的主要内容,如果未能解决你的问题,请参考以下文章