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 와 같이 이 μ½”λ“œλ₯Ό ν•œ 번만 μΆ”κ°€ν•˜λ©΄ λ©λ‹ˆλ‹€.

@MBach λŒ€μƒ ꡬ성 μš”μ†Œμ˜ componentDidMount 에 $ window.scrollTo(0, 0) λ₯Ό μ—°κ²°ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

λ‚˜λŠ” 이 행동이 맀우 λ†€λžλ‹€λŠ” 것을 μ•Œμ•˜λ‹€κ³  λ§ν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€. 거의 1λ…„ λ™μ•ˆ Next.js둜 ν”„λ‘œλ•μ…˜ μ‚¬μ΄νŠΈλ₯Ό ꡬ좕해 μ™”μ§€λ§Œ Router.push κ°€ 맨 μœ„λ‘œ λŒμ•„κ°€μ§€ μ•ŠλŠ”λ‹€λŠ” 것을 μ΄μ œμ„œμ•Ό λ°œκ²¬ν–ˆμŠ΅λ‹ˆλ‹€. μ €λŠ” 항상 Router.push κ°€ <Link> 처럼 ν–‰λ™ν•œλ‹€κ³  β€‹β€‹μƒκ°ν–ˆμŠ΅λ‹ˆλ‹€.

그리고 <a> λŒ€ <Link> 와 같은 κΈ°λ³Έ λ™μž‘μ„ μΌμΉ˜μ‹œν‚€λŠ” μΈ‘λ©΄μ—μ„œ 보면 Router.push에 ν•΄λ‹Ήν•˜λŠ” λΉ„ 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 κ°€ μ•„λ‹Œ μ΄μœ λŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ?

λ‚˜λŠ” 이 문제λ₯Ό μž¬κ²€ν† ν•΄μ•Ό ν•œλ‹€κ³  μƒκ°ν•œλ‹€.

μ£„μ†‘ν•˜μ§€λ§Œ κΈ°μ—¬μž νƒœκ·Έ: @liweinan0423 @timneutkens @exogen @goldenshun

router.push() 에 κ°•μ œλ‘œ μŠ€ν¬λ‘€μ„ 맨 μœ„λ‘œ μ΄λ™ν•˜λŠ” μ˜΅μ…˜ 이 있으면 μ’‹κ² μ§€λ§Œ 이것이 κΈ°λ³Έ 섀정이 λ˜μ–΄μ„œλŠ” μ•ˆ λœλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. 이미 κ·Έλ ‡κ²Œ ν•˜μ§€ μ•ŠλŠ”λ‹€κ³  κ°€μ •ν•˜λŠ” λͺ¨λ“  μ‚¬λžŒλ“€μ—κ²Œ 획기적인 변경이 될 것이기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

@markjackson02 이것이 λΈŒλΌμš°μ €κ°€ 이것을 μ²˜λ¦¬ν•˜λŠ” κΈ°λ³Έ 방법이기 λ•Œλ¬Έμ— 이것이 μ–΄λ–»κ²Œ μ£Όμš” λ³€κ²½ 사항인지 μ•Œ 수 μ—†μŠ΅λ‹ˆλ‹€. λ™μΌν•œ κΈ°λŠ₯에 λŒ€ν•΄ 두 가지 λ‹€λ₯Έ μ ‘κ·Ό 방식이 μžˆλ‹€λŠ” 사싀에 λ™μ˜ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

그것은 ν™•μ‹€νžˆ 획기적인 변화일 κ²ƒμž…λ‹ˆλ‹€. μ‚¬λžŒλ“€μ€ μ§€κΈˆκ³Ό 같은 λ°©μ‹μœΌλ‘œ 앱을 ꡬ좕해 μ™”μœΌλ©° 그런 λ°©μ‹μœΌλ‘œ μž‘λ™ν•˜κΈ°λ₯Ό κΈ°λŒ€ν•©λ‹ˆλ‹€.

λ‚˜λŠ” λ‘˜ λ‹€ λ™μΌν•œ κΈ°λ³Έ κΈ°λŠ₯을 μ‚¬μš©ν•˜λŠ” 것에 λ°˜λŒ€ν•˜μ§€ μ•Šμ§€λ§Œ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ λ…Έλ ₯의 κ°€μΉ˜κ°€ μžˆλ‹€κ³  μƒκ°ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

μ–΄μ¨Œλ“  이 λ¬Έμ œλŠ” λ‹«ν˜€ μžˆμœΌλ―€λ‘œ ν•˜κ³  싢은 λŒ€λ‘œ μƒˆ 문제λ₯Ό μ—΄μ–΄μ•Ό ν•©λ‹ˆλ‹€.

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

Btw, 이것은 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 와 같이 이 μ½”λ“œλ₯Ό ν•œ 번만 μΆ”κ°€ν•˜λ©΄ λ©λ‹ˆλ‹€.

당신은 ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. λŒ€μ‹  ν•˜λ‚˜μ˜ λͺ¨λ“ˆμ„ λ§Œλ“€μ–΄ ν•„μš”ν•œ ꡬ성 μš”μ†Œλ‘œ λ‚΄λ³΄λƒ…λ‹ˆλ‹€. λ”°λΌμ„œ 일단 변경이 ν•„μš”ν•˜λ©΄ ν•œ κ³³μ—μ„œ λ³€κ²½ν•΄μ•Ό ν•©λ‹ˆλ‹€.

λ˜ν•œ μ»΄ν¬λ„ŒνŠΈ λ‚΄λΆ€μ—μ„œ React Hooks(예: useRouter())만 μ‚¬μš©ν•  수 있기 λ•Œλ¬Έμ— λΌμš°ν„°λ₯Ό 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 λ“±κΈ‰