Next.js: Router.push('/link') tidak menggulir ke atas halaman saat dipicu

Dibuat pada 7 Nov 2017  ·  25Komentar  ·  Sumber: vercel/next.js

Halo,

mungkin saya kehilangan sesuatu, tetapi ketika saya menggunakan fungsi ini dan mengarahkan ulang ke halaman lain, gulir tidak diatur ulang ke atas tetapi halaman dimuat digulir ke tengah, saya tahu mengapa masalah ini terjadi, tetapi dapatkah saya memperbaikinya dengan beberapa tanda seperti JAVASCRIPT Router.pusht({pathname: '/link', scrollreset: true}) atau sesuatu seperti ini, tidak menemukan yang serupa di dokumentasi

Komentar yang paling membantu

Saya setuju harus ada opsi scrollreset . Jika Anda tidak ingin melakukannya di componentDidMount Anda juga dapat melakukannya Router.push('/link').then(() => window.scrollTo(0, 0)); .

Semua 25 komentar

apakah harus menggulir ke atas atau tidak ditentukan oleh pengguna. Saya pikir Anda bisa melakukannya di componentDidMount

Saya setuju harus ada opsi scrollreset . Jika Anda tidak ingin melakukannya di componentDidMount Anda juga dapat melakukannya Router.push('/link').then(() => window.scrollTo(0, 0)); .

Router.push('/link').then(() => window.scrollTo(0, 0)); ini adalah cara yang tepat untuk melakukannya, jangan ragu untuk menambahkannya ke readme @gragland ❤️

Terima kasih @gralagland solusi Anda tampaknya tidak terlalu jelek, tetapi alangkah baiknya memiliki opsi seperti itu untuk menjaga prinsip KERING. Satu-satunya solusi cepat untuk saat ini adalah membuat template langsung untuk menulis ini

Woaw... Maksudmu saya perlu meninjau setiap halaman untuk menambahkan .then() ! Omong-omong, saya menggunakan next-routes , jadi apakah ada cara untuk menambahkan ini secara global, hanya dengan menambahkan kode ini sekali, seperti addRequestTransform jika Anda perlu menambahkan beberapa header sebelum memanggil API.

@MBach Anda juga dapat menghubungkan window.scrollTo(0, 0) pada componentDidMount dari komponen target.

Saya hanya ingin berpadu dan mengatakan saya menemukan perilaku ini sangat mengejutkan. Telah membangun situs produksi dengan Next.js selama hampir satu tahun sekarang dan baru sekarang mengetahui bahwa Router.push tidak kembali ke atas – saya selalu berpikir Router.push berperilaku persis seperti <Link> tetapi hanya cara terprogram untuk melakukannya.

Dan dalam hal pencocokan perilaku default seperti <a> vs. <Link> , non-SPA yang setara dengan Router.push tampaknya akan menyetel window.location yang juga mengembalikan Anda ke bagian atas halaman, bukan? Itu akan lebih masuk akal sebagai perilaku default bagi saya.

@gragland tidak berfungsi

Untuk membuatnya bekerja secara global, Anda dapat menggunakan pendengar acara router next.js bawaan: Router.events.on('routeChangeComplete', () => { window.scrollTo(0, 0); }); .
Tempatkan saja ini di komponen yang dibagikan di semua halaman, misalnya header.

@timneutkens Apakah ada alasan mengapa perilaku gulir default untuk perintah Router.push dan <Link> berbeda? Sepertinya bug yang jelas bagi saya bahwa mereka berperilaku berbeda.

Router.back() tidak mengembalikan janji, tetapi memiliki masalah yang sama, apa yang harus dilakukan, menggulir ke atas secara manual?

@alexsenichev Apakah Anda mencoba solusi @macmenak ?

<Link href="/product/[id]" as={ /produk/${item.id} } beforePopState={()=>{ window.screenTop = 0; }}> <a> <h6>{item.name}</h6> </a> </Link>

Hai. Mengapa komponen Link default scroll ke atas true tetapi Router.push tidak?

Saya pikir masalah ini harus ditinjau kembali.

Maaf tapi menandai kontributor: @liweinan0423 @timneutkens @exogen @goldenshun

Akan lebih baik jika ada opsi pada router.push() untuk memaksa gulir ke atas, tetapi saya tidak berpikir itu harus default karena itu akan menjadi perubahan besar bagi semua orang yang sudah menganggap itu tidak melakukan ini.

@ markjackson02 Saya tidak melihat bagaimana ini akan menjadi perubahan yang melanggar karena ini adalah cara default browser menangani ini. Saya tidak setuju dengan fakta bahwa kami memiliki dua pendekatan berbeda untuk fungsi yang sama.

Itu pasti akan menjadi perubahan yang menghancurkan. Orang-orang telah membangun aplikasi dengan cara sekarang dan mengharapkannya berfungsi seperti itu.

Saya tidak menentang mereka berdua memiliki fungsi default yang sama tetapi saya tidak berpikir itu sepadan dengan upaya migrasi.

Bagaimanapun, masalah ini sudah ditutup jadi kita harus membuka masalah baru dengan apa pun yang ingin kita lakukan.

@ markjackson02 OMHO, perubahan utamanya adalah belum berfungsi seperti itu! Perilaku yang salah sudah dibuat. Jadi saya pikir itu akan menjadi ide yang baik untuk meletakkannya seperti yang seharusnya. Tapi saya setuju dengan Anda, kontributor mungkin tidak akan memberikan perhatian di sini.

@Timer @timneutkens Juga, digigit oleh perbedaan perilaku Link dan Router.push . FWIW, +1 untuk menambahkan ke options dari Router.push karena itu akan membuatnya tetap kompatibel.

Anda dapat menggunakan ini untuk merutekan dan menggulir ke bagian atas halaman:

// route using nextjs router and scroll to the top of the page
const routeToTop = (router, ...args) => {
    if(typeof window !== 'undefined') window.scrollTo(0, 0)
    return router.push.apply(router, args)
}

// usage

const router = useRouter()

routeToTop(router, '/my/page')

routeToTop(router, '/articles/[slug]', `/articles/${article.slug}`)

routeToTop(router, {
    pathname: '/search',
    query: {q: searchQuery},
})

Btw, ini bukan pengalaman pengguna yang menyenangkan seperti perilaku Link , karena Anda langsung menggulir ke bagian atas halaman alih-alih saat halaman berikutnya dimuat.

Saya menambahkan masalah terkait di sini untuk mereka yang tertarik: https://github.com/vercel/next.js/issues/15206

FWIW, inilah pendapat saya tentang solusi yang dibagikan dalam masalah terkait.

import { useRouter } from 'next/router';
import { useEffect } from 'react';

/**
 * React hook that forces a scroll reset to a particular set of coordinates in the document
 * after `next/router` finishes transitioning to a new page client side. It smoothly scrolls back to
 * the top by default.
 *
 * <strong i="6">@see</strong> https://github.com/vercel/next.js/issues/3249
 * <strong i="7">@see</strong> https://github.com/vercel/next.js/issues/15206
 * <strong i="8">@see</strong> https://developer.mozilla.org/en-US/docs/Web/API/ScrollToOptions
 * <strong i="9">@param</strong> {ScrollOptions} [options={}] Hook options.
 * <strong i="10">@param</strong> {ScrollBehavior} [options.behavior='smooth'] Specifies whether the scrolling should animate smoothly,
 *  or happen instantly in a single jump.
 * <strong i="11">@param</strong> {number} [options.left=0] Specifies the number of pixels along the X axis to scroll the window.
 * <strong i="12">@param</strong> {number} [options.top=0] Specifies the number of pixels along the Y axis to scroll the window.
 */
function useRouterScroll({ behavior = 'smooth', left = 0, top = 0 } = {}) {
  const router = useRouter();
  useEffect(() => {
    // Scroll to given coordinates when router finishes navigating
    // This fixes an inconsistent behaviour between `<Link/>` and `next/router`
    // See https://github.com/vercel/next.js/issues/3249
    const handleRouteChangeComplete = () => {
      window.scrollTo({ top, left, behavior });
    };

    router.events.on('routeChangeComplete', handleRouteChangeComplete);

    // If the component is unmounted, unsubscribe from the event
    return () => {
      router.events.off('routeChangeComplete', handleRouteChangeComplete);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [behavior, left, top]);
}

export default useRouterScroll;

Gunakan di suatu tempat di bagian atas pohon komponen Anda ( _app.js berfungsi).

// _app.js
function MyApp({ Component, pageProps }) {
  // Make sure pages scroll to the top after we navigate to them using `next/router`
  useRouterScroll();

  /* ... */
}

export default MyApp;

@nfantone kapan bidang ini berubah? behavior, left, top . Di belakang dan ke depan tidak bekerja untuk saya.

@rakeshshubhu Ini hanya mempengaruhi navigasi melalui next/router .

Woaw... Maksudmu saya perlu meninjau setiap halaman untuk menambahkan .then() ! Omong-omong, saya menggunakan next-routes , jadi apakah ada cara untuk menambahkan ini secara global, hanya dengan menambahkan kode ini sekali, seperti addRequestTransform jika Anda perlu menambahkan beberapa header sebelum memanggil API.

Anda tidak harus. Saya malah membuat satu modul dan mengekspornya ke komponen-komponen yang membutuhkannya. Jadi begitu itu perlu diubah, Anda mengubah satu tempat itu.

Anda juga melihat saya melewatkan router sebagai param karena Anda hanya dapat menggunakan React Hooks misalnya useRouter() di dalam komponen

export const navigate = (event, url, router) => {
  event.preventDefault();
  event.stopPropagation();

  // Force scrolling to top
  router.push(url).then(() => window.scrollTo(0, 0));
};
Apakah halaman ini membantu?
0 / 5 - 0 peringkat