Next.js: Router.push( '/ link')は、トリガーされたときにページの上部をスクロールしません

作成日 2017年11月07日  ·  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));これは正しい方法です。readme @gragland❤️に自由に追加してください。

@gralaglandに感謝します。あなたのソリューションはそれほど醜いものではないようですが、DRYプリンシペを維持するためのそのようなオプションがあると便利です。 今のところ唯一の速い解決策は、これを書くためのライブテンプレートを作成することです😅

うわー... .then()を追加するには、すべてのページを確認する必要があるということです。 ちなみに、私はnext-routesを使用しているので、APIを呼び出す前にヘッダーを追加する必要がある場合は、 addRequestTransformのように、このコードを1回追加するだけで、これをグローバルに追加する方法があります。

@MBachは、tragetコンポーネントのcomponentDidMount window.scrollTo(0, 0)をフックすることもできます。

チャイムを鳴らして、この動作が非常に驚くべきものだと思ったと言いたいだけです。 Next.jsを使用して本番サイトを構築してからほぼ1年が経ちましたが、 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()はpromiseを返しませんが、同じ問題があります。手動で上にスクロールするとどうすればよいですか?

@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がないのはなぜですか?

この問題を再検討する必要があると思います。

申し訳ありませんが、寄稿者にタグを付けます: @ liweinan0423 @timneutkens @exogen @goldenshun

router.push()に強制的に上にスクロールするオプションがあればいいのですが、これを行わないと仮定しているすべての人にとっては重大な変更になるため、デフォルトではないと思います。

@ markjackson02これはブラウザがこれを処理するデフォルトの方法であるため、これがどのように重大な変更になるかわかりません。 同じ機能に対して2つの異なるアプローチがあるという事実に同意しません。

それは間違いなく重大な変化になるでしょう。 人々は現在の方法でアプリを構築しており、そのように機能することを期待しています。

どちらも同じデフォルト機能を持っていることに反対しているわけではありませんが、移行に取り組む価値はないと思います。

とにかく、この問題はクローズされているので、やりたいことは何でも新しい問題を開く必要があります。

@ markjackson02 OMHO、重大な変更は、まだそのように機能していないことです! 間違った振る舞いはすでに行われています。 ですから、そうあるべき姿にするといいと思います。 しかし、私はあなたに同意します、貢献者はおそらくここで注意を向けないでしょう。

@Timer @timneutkensまた、 LinkRouter.pushの動作の違いに噛まれました。 FWIW、 Router.pushoptionsに+1すると、下位互換性が維持されます。

これを使用して、ページの上部にルーティングおよびスクロールできます。

// 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()を追加するには、すべてのページを確認する必要があるということです。 ちなみに、私はnext-routesを使用しているので、APIを呼び出す前にヘッダーを追加する必要がある場合は、 addRequestTransformのように、このコードを1回追加するだけで、これをグローバルに追加する方法があります。

あなたはする必要はありません。 代わりに、1つのモジュールを作成し、それを必要とするコンポーネントにエクスポートします。 したがって、変更が必要になった場合は、その1つの場所を変更します。

また、コンポーネント内でuseRouter()などのReactフックしか使用できないため、ルーターをparamとして渡していることに気付きます。

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 評価