Next.js: لا تقوم Router.push ('/ link') بالتمرير أعلى الصفحة عند التشغيل

تم إنشاؤها على ٧ نوفمبر ٢٠١٧  ·  25تعليقات  ·  مصدر: vercel/next.js

مرحبا،

ربما أفتقد شيئًا ما ، ولكن عند استخدام هذه الوظيفة وإعادة التوجيه إلى صفحة أخرى ، لا يتم إعادة تعيين التمرير إلى الأعلى ولكن يتم تمرير الصفحة إلى المنتصف ، وأنا أعلم سبب حدوث هذه المشكلة ، ولكن يمكنني بطريقة ما إصلاحها ببعض العلامات مثل JAVASCRIPT Router.pusht({pathname: '/link', scrollreset: true}) أو شيء من هذا القبيل ، لم يتم العثور على أي شيء مشابه في الوثائق

التعليق الأكثر فائدة

أوافق على أنه يجب أن يكون هناك خيار scrollreset . إذا كنت لا تريد القيام بذلك في componentDidMount يمكنك أيضًا القيام بـ Router.push('/link').then(() => window.scrollTo(0, 0)); .

ال 25 كومينتر

يقرر المستخدم ما إذا كان يجب التمرير إلى أعلى أم لا. أعتقد أنه يمكنك القيام بذلك في componentDidMount

أوافق على أنه يجب أن يكون هناك خيار scrollreset . إذا كنت لا تريد القيام بذلك في componentDidMount يمكنك أيضًا القيام بـ Router.push('/link').then(() => window.scrollTo(0, 0)); .

Router.push('/link').then(() => window.scrollTo(0, 0)); هذه هي الطريقة الصحيحة للقيام بذلك ، لا تتردد في إضافته إلى الملف التمهيدي gragland ❤️

شكرًا gralagland ، يبدو أن الحل الخاص بك ليس قبيحًا للغاية ، ولكن سيكون من الجيد أن يكون لديك مثل هذا الخيار للحفاظ على DRY Principe. الحل السريع الوحيد في الوقت الحالي هو إنشاء نموذج مباشر لكتابة هذا 😅

واو ... تقصد أنني بحاجة لمراجعة كل صفحة لإضافة .then() ! بالمناسبة ، أنا أستخدم المسارات التالية ، لذا هل هناك طريقة لإضافة هذا عالميًا ، فقط لإضافة هذا الرمز مرة واحدة ، مثل addRequestTransform إذا كنت بحاجة إلى إضافة بعض العناوين قبل استدعاء واجهة برمجة التطبيقات.

MBach يمكنك أيضًا ربط window.scrollTo(0, 0) بمكون التتبع componentDidMount .

أريد فقط أن أتحدث وأقول إنني وجدت هذا السلوك مفاجئًا للغاية. كنت أقوم ببناء مواقع إنتاج باستخدام Next.js لمدة عام تقريبًا حتى الآن واكتشفت للتو أن Router.push لم يعد يعود إلى الأعلى - اعتقدت دائمًا أن Router.push يتصرف تمامًا مثل <Link> ولكنها كانت مجرد طريقة برمجية للقيام بذلك.

وفيما يتعلق بمطابقة السلوك الافتراضي مثل <a> مقابل <Link> ، فإن المكافئ بخلاف SPA لـ Router.push يبدو أنه يقوم بتعيين window.location والذي يعيدك أيضًا في أعلى الصفحة ، أليس كذلك؟ سيكون من المنطقي أكثر باعتباره السلوك الافتراضي بالنسبة لي.

gragland لا يعمل

لجعله يعمل على مستوى العالم ، يمكنك استخدام مستمع أحداث جهاز التوجيه next.js المدمج: Router.events.on('routeChangeComplete', () => { window.scrollTo(0, 0); }); .
فقط ضع هذا في مكون مشترك عبر جميع الصفحات مثل العنوان.

timneutkens هل هناك سبب يفسر اختلاف سلوك التمرير الافتراضي للأمر Router.push و <Link> ؟ يبدو لي أنه خطأ واضح بالنسبة لي أنهم يتصرفون بشكل مختلف.

Router.back () لا يعطي الوعد ، لكن لديه نفس المشكلة ، ماذا تفعل ، التمرير يدويًا لأعلى؟

alexsenichev هل جربت حل macmenak ؟

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

مرحبا. لماذا لدينا التمرير الافتراضي للمكون Link لأعلى true لكن Router.push لا؟

أعتقد أنه يجب إعادة النظر في هذه المسألة.

آسف ولكن وضع علامات على المساهمين : @ liweinan0423timneutkensexogengoldenshun

سيكون من الرائع أن يكون هناك خيار في router.push() لفرض التمرير لأعلى ، لكنني لا أعتقد أنه يجب أن يكون افتراضيًا لأنه سيكون تغييرًا مفاجئًا لكل شخص يفترض بالفعل أنه لا يقوم بذلك.

@ markjackson02 لا أرى كيف سيكون هذا تغييرًا مفاجئًا لأن هذه هي الطريقة الافتراضية التي سيتعامل بها المتصفح مع هذا الأمر. لا أتفق مع حقيقة أن لدينا نهجين مختلفين لنفس الوظيفة.

سيكون بالتأكيد تغيير جذري. كان الناس يصممون التطبيقات بالطريقة التي هي عليها الآن ويتوقعون أن تعمل بهذه الطريقة.

أنا لست ضد امتلاكهما نفس الوظيفة الافتراضية ولكن لا أعتقد أن الأمر يستحق جهود الترحيل.

على أي حال ، تم إغلاق هذه المشكلة ، لذا يجب أن نفتح مشكلة جديدة مع كل ما نريد القيام به.

@ markjackson02 OMHO ، التغيير الكبير هو أنه لا يعمل بهذه الطريقة بعد! تم ارتكاب السلوك الخاطئ بالفعل. لذلك أعتقد أنه سيكون فكرة جيدة أن أضعها بالطريقة التي ينبغي لها. لكنني أتفق معك ، فربما لن يولي المساهمون اهتمامًا هنا.

Timertimneutkens أيضًا ، تعرض للعض من الاختلاف في السلوك Link و Router.push . FWIW ، +1 لإضافة إلى options من Router.push لأن ذلك سيجعله متوافقًا مع الإصدارات السابقة.

يمكنك استخدام هذا للتوجيه والتمرير إلى أعلى الصفحة:

// 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},
})

راجع للشغل ، هذا ليس جيدًا لتجربة المستخدم مثل سلوك Link ، نظرًا لأنك تقوم بالتمرير إلى أعلى الصفحة على الفور بدلاً من تحميل الصفحة التالية.

لقد أضفت هنا مشكلة ذات صلة للمهتمين: https://github.com/vercel/next.js/issues/15206

FWIW ، إليك رأيي في حل بديل تمت مشاركته في مشكلة ذات صلة.

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;

استخدمه في مكان ما أعلى شجرة المكوّنات ( _app.js يعمل).

// _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 متى تتغير هذه الحقول؟ behavior, left, top . في الخلف والأمام لا يعمل لدي.

rakeshshubhu هذا يؤثر فقط على التنقل من خلال next/router .

واو ... تقصد أنني بحاجة لمراجعة كل صفحة لإضافة .then() ! بالمناسبة ، أنا أستخدم المسارات التالية ، لذا هل هناك طريقة لإضافة هذا عالميًا ، فقط لإضافة هذا الرمز مرة واحدة ، مثل addRequestTransform إذا كنت بحاجة إلى إضافة بعض العناوين قبل استدعاء واجهة برمجة التطبيقات.

لا داعي لذلك. بدلاً من ذلك ، أقوم بإنشاء وحدة واحدة وتصديرها إلى تلك المكونات التي تحتاجها. لذلك بمجرد أن تحتاج إلى تغيير ، يمكنك تغيير ذلك المكان الفردي.

تلاحظ أيضًا أنني أمرر الموجه كمعلمة حيث يمكنك فقط استخدام React Hooks مثل useRouter () داخل أحد المكونات

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

  // Force scrolling to top
  router.push(url).then(() => window.scrollTo(0, 0));
};
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات