こんにちは、
何かが足りないかもしれませんが、この関数を使用して別のページにリダイレクトすると、スクロールは上にリセットされませんが、ページの読み込みは中央にスクロールされます。この問題が発生する理由はわかりますが、 JAVASCRIPT Router.pusht({pathname: '/link', scrollreset: true})
などのフラグで修正できますか?
上にスクロールするかどうかは、ユーザーが決定します。 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また、 Link
とRouter.push
の動作の違いに噛まれました。 FWIW、 Router.push
のoptions
に+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));
};
最も参考になるコメント
scrollreset
オプションがあるべきだということに同意します。 あなたがそれを行うにはしたくない場合はcomponentDidMount
あなたも行うことができますRouter.push('/link').then(() => window.scrollTo(0, 0));
。