Gatsby JS:预加载器永远加载 [英] Gatsby JS: Preloader is loading forever

查看:50
本文介绍了Gatsby JS:预加载器永远加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Gatsby应用程序上通过jQuery复制了一个简单的整页预加载器.但是,预加载器可以正常工作,而不会在4秒钟后消失,而是永远在生产环境中消失,而在本地则可以正常工作.

这是我的 Preloader 组件:

  import从'react'进行Reactconst Preloader =()=>{返回 (< div id ="loader-wrapper">< div id =加载程序">/div< div className ="loader-section section-left"</div< div className ="loader-section section-right"</div</div>)}导出默认的预加载器 

然后在我的 script.js (包含在< Helmet> 中)上:

  jQuery.noConflict();(函数($){var windows = $(window);/*预加载器*/setTimeout(function(){$('body').addClass('loaded');$('h1').css('color','#222222');},400);})(jQuery); 

我在 index.js 上添加了此预加载器:

 返回(<><预加载器/>< SEO/>< div className =主容器"><布局><标题/><推荐书标题=推荐书"./>< Blogs title =最新博客";blogs = {blogs} showAllBlogLinks/><地图/></布局></div></>)} 

您知道是什么原因造成的,以及如何解决此问题?

解决方案

几个月前,我也遇到了类似的问题,解决方法严格取决于实现和您的代码.基本上,正在发生的事情是,React's不了解他需要补充水分,因为指向一些全局对象,如React之外的DOM的 window document 生态系统(不使用状态)可能会由于jQuery而阻止补液.

所有可能绕过此问题的解决方案都是修补程序(例如尝试添加缓存).理想的解决方案是避免使用带有操纵虚拟DOM(vDOM)的React的直接指向DOM的jQuery.这条线破坏了您的补液功能:

  var windows = $(window); 

最奇怪的是在本地运行npx gatsby时开发它可以显示我的所有数据.真的很奇怪

这不是,再次出现: gatsby开发在浏览器中发生,在浏览器中有一个 window 对象,另一方面,发生了 gatsby build 在没有 window 或其他服务器的服务器(节点)中全局对象,因为它们甚至都没有创建.

此外,您可以轻松转换此代码段:

  setTimeout(function(){document.querySelector("body").classList.add("loaded");document.querySelector("h1").style =颜色:#222222";},400) 

使用钩子插入基于React的容器中:

  const [loader,setLoader] = useState(true);useEffect(()=> {setTimeout(()=> {setLoader(假)},400)},[])返回 (<>< SEO/>{loader?<预加载器/>:< div className =主容器"><布局><标题/><推荐书标题=推荐书"./>< Blogs title =最新博客";blogs = {blogs} showAllBlogLinks/><地图/></布局></div>}</>)} 

作为简历.您最初将加载程序设置为true( useState(true)),然后在加载DOM树后( useEffect 且空的 deps [] ),则触发您的 setTimeout 函数,该函数会将 loader 的值从 true 切换为 false.这将在以下位置使用三元条件选择要渲染的组件: loader?<预加载器/>:< OtherComponents/>

如果需要使用 window 大小对象,则可以使用基于React的方法,例如提供的此处.

有没有一种方法可以改善这种情况并使每次加载预加载器您访问另一个页面?

是的,因为所有页面将共享它,所以想法是将加载程序逻辑移至< Layout> 组件.

  const Layout =({childrens))=>{const [loader,setLoader] = useState(true);useEffect(()=> {setTimeout(()=> {setLoader(假)},400)},[])返回< section className = {`site__wrapper`}><标题/>< main> {loader?<预加载器/>:children}</main></section> ;;}; 

我不知道您的< Layout> 组件的外观如何,但是其想法是添加类似的内容.由于您的< Layout> 在您的站点之间共享,因此每次重新渲染组件都会对该组件进行补水,从而将初始加载程序状态强制为 true 并将其更改为 false (400毫秒),呈现 children ,这是包装在其他页面上的< Layout> 组件中的所有内容.

I copied a simple full page preloader via jQuery on my Gatsby app. The preloader works however instead of disappearing after 4 seconds its loading forever on production but on local it works just fine.

Here's my Preloader component:

import React from 'react'

 const Preloader = () => {
    return (
        <div id="loader-wrapper">
        <div id="loader"></div>
        <div className="loader-section section-left"></div>
        <div className="loader-section section-right"></div>
    </div>
    )
}

export default Preloader

And then on my script.js (which was included inside <Helmet>):

jQuery.noConflict();
    
(function ($) {

    var windows = $(window);

    /* preloader */
    setTimeout(function(){
        $('body').addClass('loaded');
        $('h1').css('color','#222222');
    }, 400);
    
   
})(jQuery);

I added this preloader on my index.js:

return (
     <>
    <Preloader />
    <SEO />
    <div className="main-container">
      <Layout>
      <Header />
      <Testimonials title="Testimonials" />
      <Blogs title="Latest Blogs" blogs={blogs} showAllBlogLinks/>
      <Map />
      </Layout>
    </div> 
    </>
  )
}

Any idea what's causing this and how to fix it?

解决方案

I've faced a similar issue a few months ago and the fix depends strictly on the implementation and your code. Basically, what is happening is that React's doesn't understand that he needs to rehydrate some components because pointing to some global objects as window or document of the DOM, outside the React's ecosystem (without using states) may block that rehydration, in your cause, because of jQuery.

All the possible solutions that bypass this issue will be patches (like trying to add the cache). The ideal solution would avoid using jQuery, which points directly to the DOM, with React, which manipulates the virtual DOM (vDOM). This line is breaking your rehydration:

var windows = $(window);

The most weird thing here is that on local upon running npx gatsby develop it shows all of my data. Really weird

It's not, again: gatsby develop occurs in the browser, where there's a window object, on the other hand, gatsby build occurs in the server (Node) where there's no window or other global objects because they are not even created.

In addition, you can easily transform this snippet:

setTimeout(function() {
    document.querySelector("body").classList.add("loaded");
    document.querySelector("h1").style = "color: #222222";
}, 400)

Into a React-based one, using hooks:

   const [loader, setLoader]=useState(true);

   useEffect(()=>{
    setTimeout(()=> {
       setLoader(false)
    }, 400)
   }, [])

return (
     <>
     <SEO />
    {loader 
      ? <Preloader />
      : <div className="main-container">
         <Layout>
            <Header />
            <Testimonials title="Testimonials" />
            <Blogs title="Latest Blogs" blogs={blogs} showAllBlogLinks/>
            <Map />
         </Layout>
       </div> 
     }
    </>
  )
}

As a resume. You are setting initially the loader as true (useState(true)), and once the DOM tree is loaded (useEffect with empty deps, []), you trigger your setTimeout function, which toggles the value of loader from true to false. This will choose what component render using a ternary condition at: loader ? <Preloader/> : <OtherComponents />

If you need to use the window size object, you can use a React-based approach, like the one provided here.

Is there a way to improve this and make the preloader loads everytime you visit another page?

Yes, the idea is to move that loader logic to the <Layout> component, since all the pages will share it:

const Layout = ({ children }) => {
       const [loader, setLoader]=useState(true);
    
       useEffect(()=>{
        setTimeout(()=> {
           setLoader(false)
        }, 400)
       }, [])

  return  <section className={`site__wrapper`}>
    <Header />
    <main>{loader ? <Preloader/> :  children}</main>
  </section>;
};

I don't know how your <Layout> component looks like but the idea is to add something similar. Since your <Layout> is shared across your site, each re-rendering of the component will rehydrate this component, forcing the initial loader state as true and changing it to false at 400ms, rendering the children, which is everything wrapped inside the <Layout> component on other pages.

这篇关于Gatsby JS:预加载器永远加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆