klendi / react-top-loading-bar

A very simple, highly customisable youtube-like react loader component.
https://klendi.github.io/react-top-loading-bar/
MIT License
708 stars 60 forks source link

How can I use it with Next.js? #10

Closed essovius closed 5 years ago

essovius commented 5 years ago

Hello there, is there any way to use it with next.js?

klendi commented 5 years ago

You just install it to your project and import it? I think it should work with next.js too. Then the examples are pretty straight forward. You just have to find a solution to make the bar global. You can use redux also https://github.com/klendi/react-movies this project uses react-top-loading-bar with redux. Its a pretty nice solution. :) If it doesn't work in next.js tell me

essovius commented 5 years ago

I've added the following code to the _app.js to make it global. Currently seems like it's working but sometimes it starts over by itself after page is loaded.

import App from 'next/app'
import React, { Component } from 'react'
import { ThemeProvider } from 'styled-components'
import GlobalStyles from '../styles/GlobalStyles'
import theme from '../styles/Theme'
import Router from 'next/router'
import LoadingBar from 'react-top-loading-bar'

Router.events.on('routeChangeStart', () => LoadingBar.ref.continuousStart())
Router.events.on('routeChangeComplete', () => LoadingBar.ref.complete())
Router.events.on('routeChangeError', () => LoadingBar.ref.complete())

export default class MyApp extends App {

  static async getInitialProps ({ Component, router, ctx }) {
    let pageProps = {}
    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }
    return { pageProps }
  }

  render () {
    const { Component, pageProps } = this.props  
    return (
      <ThemeProvider theme={theme}>
        <>
        <GlobalStyles />
        <LoadingBar
          height={3}
          color='#f11946'
          onRef={r => (LoadingBar.ref = r)}
        />
        <Component {...pageProps} />
        </>
      </ThemeProvider>
    )
  }

}
gerkim62 commented 8 months ago

"use client";

import { useEffect, useRef, useState } from "react"; import Link, { LinkProps } from "next/link"; import LoadingBar, { LoadingBarRef } from "react-top-loading-bar"; import { usePathname } from "next/navigation";

interface CustomLinkProps extends Omit<React.AnchorHTMLAttributes, keyof LinkProps>, LinkProps { loaderColor?: string; }

const CustomLink: React.FC = ({ children, loaderColor = "#007bff", ...rest }) => { const [wontNavigate, setWontNavigate] = useState(false); const loadingBarRef = useRef(null);

const { href } = rest; const pathname = usePathname();

if (!wontNavigate && (href === pathname || href.toString().startsWith("#"))) { setWontNavigate(true); }

useEffect(() => { if (loadingBarRef.current) { loadingBarRef.current.complete(); } }, [pathname]);

const handleClick = () => { if (loadingBarRef.current) { loadingBarRef.current.continuousStart(); // No error now if (wontNavigate) { return loadingBarRef.current.complete(); } setTimeout(() => { loadingBarRef.current?.complete(); }, 5000); } };

return ( <> <Link {...rest} onClick={handleClick}> {children}

</>

); };

export default CustomLink;

this might help you to use it with nextjs