Next.js: λ‹€μŒ 9-κΈ°λŠ₯적 ꡬ성 μš”μ†Œλ₯Ό μžμ‹μœΌλ‘œ μ‚¬μš©<link/> μ‹¬νŒ κ²½κ³  λ°œμƒ

에 λ§Œλ“  2019λ…„ 07μ›” 12일  Β·  32μ½”λ©˜νŠΈ  Β·  좜처: vercel/next.js

버그 μ‹ κ³ 

버그 μ„€λͺ…

κΈ°λŠ₯ ꡬ성 μš”μ†Œλ₯Ό <Link/> 의 μžμ‹μœΌλ‘œ μ‚¬μš©ν•˜λ©΄ λ‹€μŒκ³Ό 같은 μ›μΈμ΄λ©λ‹ˆλ‹€.

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

이것은 v8 => v9μ—μ„œ μ—…κ·Έλ ˆμ΄λ“œ ν•œ 후에 만 β€‹β€‹λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.

μž¬ν˜„ν•˜λ €λ©΄

볡제 μ €μž₯μ†Œ : https://github.com/nickluger/nextjs-link-ref-functional-comp-warning

μ˜ˆμƒλ˜λŠ” 행동

<Link/> 도 κΈ°λŠ₯ ꡬ성 μš”μ†Œμ™€ ν•¨κ»˜ μž‘λ™ν•΄μ•Όν•˜λ©° κ²½κ³ λ₯Ό ν‘œμ‹œν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

μ‹œμŠ€ν…œ 정보

  • Next.js 버전 : 9.0.1

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

Link λ‚΄μ—μ„œ μ‚¬μš©λ˜λŠ” λͺ¨λ“  κΈ°λŠ₯ ꡬ성 μš”μ†Œλ₯Ό μˆ˜λ™μœΌλ‘œ λž˜ν•‘ ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ? 이λ₯Όμœ„ν•œ 더 쉽고 덜 반볡적 인 μ†”λ£¨μ…˜μ΄ μžˆμ–΄μ•Όν•˜μ§€ μ•ŠμŠ΅λ‹ˆκΉŒ? 적어도 <Link href="/" forwardRef>...</Link> ?

λͺ¨λ“  32 λŒ“κΈ€

여기도 λ§ˆμ°¬κ°€μ§€μž…λ‹ˆλ‹€. λ‹€μŒκ³Ό 같은 μ‚¬μš©μž 지정 ꡬ성 μš”μ†Œλ₯Ό μ‚¬μš©ν•˜λ©΄ 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.

        <Link href="/href">
          <Button
            type="custom"
            color="#FCFCFC"
          >
             buttonText
          </Button>
        </Link>

μ΄λŠ” ꡬ성 μš”μ†Œλ₯Ό μžμ‹μœΌλ‘œ μ‚¬μš©ν•  λ•Œλ§Œ λ°œμƒν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ κ²½κ³ λ₯Ό μ œκ³΅ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

        <Link href="/href">
          <button
            type="custom"
            color="#FCFCFC"
          >
            buttonText
          </button>
        </Link>

        <Link href="/href">
          <a>
            <Button
              type="custom"
              color="#FCFCFC"
            >
              buttonText
            </Button>
          </a>
        </Link>

이 버그λ₯Ό ν•΄κ²°ν•  방법이 μžˆμŠ΅λ‹ˆκΉŒ? μš°λ¦¬λŠ” 타이프 슀크립트 지원과 같은 일뢀 κΈ°λŠ₯을 μ‹€μ œλ‘œ ν™œμš©ν•˜κ³  싢은 경우 9둜 μ΄λ™ν•˜λŠ” 것이 μ°¨λ‹¨λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 9.0.3으둜 좩돌 ν•œ 것을 μ•Œμ•„ μ°¨ λ ΈμŠ΅λ‹ˆλ‹€. : /

λ‹€μŒκ³Ό 같이 μΌμ‹œμ μœΌλ‘œ μŒμ†Œκ±°λ₯Ό μ‹œλ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

// TODO: Muting error, fix as soon as zeit/next.js/issues/7915 resolved
const originalError = console.error;

console.error = (...args) => {
  if (/Warning.*Function components cannot be given refs/.test(args[0])) {
    return;
  }
  originalError.call(console, ...args);
};

여기에도 같은 λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€.

<Link/> λ₯Ό μ‚¬μš©ν•˜μ—¬ μ‚¬μš©μž 지정 ꡬ성 μš”μ†Œλ₯Ό λž˜ν•‘ν•˜λŠ” 경우 λ‹€μŒκ³Ό 같이 ref 전달할 수 μžˆμŠ΅λ‹ˆλ‹€.

const CustomComponent = React.forwardRef(function CustomComponent(props, ref) {
  return (
    <div/>
  );
});
<Link href={"/"}>
  <CustomComponent/>
</Link>

κ²½κ³ κ°€ μ‚¬λΌμ§‘λ‹ˆλ‹€.

9.0.4-canary.2 μ—…λ°μ΄νŠΈν–ˆμ§€λ§Œ μ—¬μ „νžˆ 본체에 κ²½κ³ κ°€ ν‘œμ‹œλ©λ‹ˆλ‹€. λ‚΄κ°€ λ­”κ°€λ₯Ό λ†“μΉ˜κ³  μžˆμŠ΅λ‹ˆκΉŒ?

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Check the render method of `Link`.

@ th0th ꡬ성 μš”μ†Œλ₯Ό React.forwardRef λž˜ν•‘ν•΄μ•Όν•©λ‹ˆλ‹€. 이 같은:

import React from 'react'
import Link from 'next/link'

const CustomComponent = React.forwardRef((props, ref) => (
  <a ref={ref} {...props}>
    Click
  </a>
))

export default () => (
  <Link href='/' passHref>
    <CustomComponent/>
  </Link>
)

Link λ‚΄μ—μ„œ μ‚¬μš©λ˜λŠ” λͺ¨λ“  κΈ°λŠ₯ ꡬ성 μš”μ†Œλ₯Ό μˆ˜λ™μœΌλ‘œ λž˜ν•‘ ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ? 이λ₯Όμœ„ν•œ 더 쉽고 덜 반볡적 인 μ†”λ£¨μ…˜μ΄ μžˆμ–΄μ•Όν•˜μ§€ μ•ŠμŠ΅λ‹ˆκΉŒ? 적어도 <Link href="/" forwardRef>...</Link> ?

@nickluger에 λ™μ˜ν•˜λ©΄ 반 μ§κ΄€μ μœΌλ‘œ λ³΄μž…λ‹ˆλ‹€.

λ‹€λ₯Έ λͺ¨λ“  λΌμ΄λΈŒλŸ¬λ¦¬κ°€ λ™μΌν•œ λ°©μ‹μœΌλ‘œ forwardRef 속성을 κ΅¬ν˜„ν•΄μ•Όν•©λ‹ˆκΉŒ? μ•„λ‹ˆλ©΄ 리 μ•‘νŠΈ ν¬λ¦¬μ—μ΄ν„°λŠ” κ°œλ°œμžκ°€ forwardRef 속성을 κ΅¬ν˜„ν•˜λŠ” λŒ€μ‹  React.forwardRef ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  것이라고 μƒκ°ν–ˆμ„κΉŒμš”?

예 @nickluger에 λ™μ˜ν•©λ‹ˆλ‹€. Link λ‚΄λΆ€μ˜ λͺ¨λ“  ꡬ성 μš”μ†Œμ— λŒ€ν•΄ μˆ˜λ™μœΌλ‘œμ΄ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” 것은 κ³ ν†΅μž…λ‹ˆλ‹€.

이 문제λ₯Ό λ‹€μ‹œ μ—΄κ³  (@ijjk) 이름을 λ³€κ²½ν•΄μ•Όν•©λ‹ˆκΉŒ? μ•„λ‹ˆλ©΄ λˆ„κ΅°κ°€ 이미 μƒˆ 문제λ₯Ό μ—΄μ—ˆμŠ΅λ‹ˆκΉŒ?

여기도 λ§ˆμ°¬κ°€μ§€μž…λ‹ˆλ‹€. λ‹€μŒκ³Ό 같은 μ‚¬μš©μž 지정 ꡬ성 μš”μ†Œλ₯Ό μ‚¬μš©ν•˜λ©΄ 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.

        <Link href="/href">
          <Button
            type="custom"
            color="#FCFCFC"
          >
             buttonText
          </Button>
        </Link>

μ΄λŠ” ꡬ성 μš”μ†Œλ₯Ό μžμ‹μœΌλ‘œ μ‚¬μš©ν•  λ•Œλ§Œ λ°œμƒν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ κ²½κ³ λ₯Ό μ œκ³΅ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

        <Link href="/href">
          <button
            type="custom"
            color="#FCFCFC"
          >
            buttonText
          </button>
        </Link>

        <Link href="/href">
          <a>
            <Button
              type="custom"
              color="#FCFCFC"
            >
              buttonText
            </Button>
          </a>
        </Link>

μ½˜μ†” 였λ₯˜κ°€ λ°œμƒν•  κ°€λŠ₯성이 λ†’μŠ΅λ‹ˆλ‹€.

Warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>.

Next JSλ₯Ό μ—…κ·Έλ ˆμ΄λ“œ ν•  λ•Œμ΄ λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. κ°€λŠ” 길에 μˆ˜μ •μ΄ μžˆμŠ΅λ‹ˆκΉŒ?

forwardRefλ₯Ό μ‚¬μš©ν•˜κ³  ꡬ성 μš”μ†Œλ₯Ό λž˜ν•‘ν•˜λŠ” 방법을 잘 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€. λ‚΄ button.js νŒŒμΌμ€ ν˜„μž¬ λ‹€μŒμ„ λ‚΄ λ³΄λƒ…λ‹ˆλ‹€ ....

const Button = (props) => {
    return (<stuff />)
}

export default React.memo(Button)

μœ„λ₯Ό μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€. https://github.com/zeit/next.js/issues/8962 μ—μ„œ 후속 μž‘μ—…μ„ μ—΄μ—ˆμŠ΅λ‹ˆλ‹€.

Next JSλ₯Ό μ—…κ·Έλ ˆμ΄λ“œ ν•  λ•Œμ΄ λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. κ°€λŠ” 길에 μˆ˜μ •μ΄ μžˆμŠ΅λ‹ˆκΉŒ?

forwardRefλ₯Ό μ‚¬μš©ν•˜κ³  ꡬ성 μš”μ†Œλ₯Ό λž˜ν•‘ν•˜λŠ” 방법을 잘 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€. λ‚΄ button.js νŒŒμΌμ€ ν˜„μž¬ λ‹€μŒμ„ λ‚΄ λ³΄λƒ…λ‹ˆλ‹€ ....

const Button = (props) => {
    return (<stuff />)
}

export default React.memo(Button)

이 경우, 당신은 ν•  수 μžˆμ–΄μ•Όν•©λ‹ˆλ‹€

import {forwardRef} from 'react';
const Button = forwardRef(props, ref) => {
    return (<stuff ref={ref} />)
}

forwardRef λΆ€λΆ„. λ¬Έμ„œμ—λŠ” https://nextjs.org/docs#forcing -the-link-to-expose-href-to-its-childκ°€ μ–ΈκΈ‰λ˜μ–΄ μžˆμ§€λ§Œ μ‹œλ„ν•˜μ§€λŠ” μ•Šμ•˜μŠ΅λ‹ˆλ‹€. λ‚˜λŠ” μ΄κ²ƒμ„ν•˜λŠ” 것을 λ°œκ²¬ν–ˆλ‹€

            <Link
              href={href}
            >
              <a>
                {text}
              </a>
            </Link>

μž‘λ™ν•©λ‹ˆλ‹€ (맀우 이상해 λ³΄μž„μ—λ„ λΆˆκ΅¬ν•˜κ³ ).

9.0.2μ—μ„œμ΄ 문제 λ°œμƒ

<a></a> μ‚¬μš©ν•˜λ©΄ μž‘λ™ ν•  수 μžˆμ§€λ§Œ a11y 및 이와 μœ μ‚¬ν•œ 것을 μ‚¬μš©ν•  λ•Œ "must have href"λ“±κ³Ό 같은 λ‹€λ₯Έ 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.

νŽΈμ§‘ : 이것을 μ•Œμ•„ λ‚΄κΈ° μœ„ν•΄ 15 뢄을 λ³΄λƒˆλŠ”λ°, 그것은 맀우 μ§€λ£¨ν•˜κ³  μ‹œκ°„ 낭비이며 경고에도 λΆˆκ΅¬ν•˜κ³  μ œλŒ€λ‘œ μž‘λ™ν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.

개인적으둜 https://github.com/zeit/next.js/issues/7915#issuecomment -511792629둜

λ°˜μ‘ 쑰각 을 베어링 래퍼둜 μ‚¬μš©ν•˜λŠ”μ΄ μ†”λ£¨μ…˜μ€ μ–΄λ–»μŠ΅λ‹ˆκΉŒ?

import React, { Fragment, useRef } from 'react';
import { MyFunctionalComponent } from './my-functional-component';

const App = props => {
  const myRef = useRef();

  return ( 
    <Link href={href}>
      <Fragment>
          <MyFunctionalComponent ref={myRef} />
      </Fragment>
    </Link>
  );
}

<MyFunctionalComponent> λŠ” refλ₯Ό μ „λ‹¬ν•©λ‹ˆλ‹€.

import React, { forwardRef } from 'react';

const MyFunctionalComponent = forwardRef(props, ref) => (
  <div ref={ref} />
);

μ΄λŠ” 좜λ ₯ ( <div /> )에 μΆ”κ°€ HTML 래퍼λ₯Ό μΆ”κ°€ν•˜μ§€ μ•ŠμœΌλ©° κ΄€λ ¨ 였λ₯˜λ₯Ό νŠΈλ¦¬κ±°ν•˜μ§€ μ•Šμ•„μ•Όν•©λ‹ˆλ‹€.

@ hill84 ν₯미둭지 만 myRef μΆœμ²˜λŠ” μ–΄λ””μž…λ‹ˆκΉŒ?

@Vadorequest 이전 λŒ“κΈ€μ— μžμ„Έν•œ λ‚΄μš©μ„ μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.

@ hill84 의 μ œμ•ˆμ„
```
const ButtonLink : FC= ({children, href, ... props}) => (
<

@ hill84 의 μ œμ•ˆμ„

const ButtonLink: FC<ButtonLinkProps> = ({ children, href, ...props }) => (
  <Link href={href}>
    <><Button link {...props}>{children}</Button></>
  </Link>
);

<><Component/></> ν•˜μ§€λ§Œ Linkκ°€ μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λŒ€μ‹  <div></div> λ₯Ό μ‚¬μš©ν•΄μ•Όν•©λ‹ˆλ‹€.

ν•¨μˆ˜κ°€ ꡬ성 μš”μ†Œ λŒ€μ‹  μ†Œν’ˆμœΌλ‘œ 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” μ†”λ£¨μ…˜μ„ μ œμ•ˆν•©λ‹ˆλ‹€.

const propsUserBtn = user => ({
    className: "h-10 w-10 font-black rounded-full bg-orange-200 text-teal-700",
    title: user.first_name + ' ' + user.last_name,
    children: (user.first_name.charAt(0) + user.last_name.charAt(0)).toUpperCase()
})
<Link href='/profile'>
    <button { ...propsUserBtn(user) } />   
</Link>

확인, μž‘λ™ν•©λ‹ˆλ‹€!

이 μ‹¬νŒμ΄ μ™œ ν•„μš”ν•œκ°€μš”? passHref κ°€ <Link /> μ—μ„œ μ‚¬μš©λ  λ•Œ κΈ°λ³Έ λž˜ν•‘ 된 ꡬ성 μš”μ†Œμ—μ„œ href 의 μ˜¬λ°”λ₯Έ 배치λ₯Ό 보μž₯ν•˜λŠ” κ²ƒμž…λ‹ˆκΉŒ?

λ‚΄ μ‚¬μš©μž μ •μ˜

λ˜λŠ” ꡬ성 μš”μ†Œμ—μ„œ href 의 μœ„μΉ˜λ₯Ό β€‹β€‹μ§€μ •ν•΄μ•Όν•˜λŠ” 경우 적어도 옡트 인 κΈ°λŠ₯μ΄μ–΄μ•Όν•©λ‹ˆλ‹€. <Link href="/" passHref useRef /> ?

μ°Έμ‘°λ₯Ό μ‚¬μš©μž 지정 ꡬ성 μš”μ†Œλ‘œ μ „λ‹¬ν•˜κΈ° μœ„ν•΄ λ‹€λ₯Έ λͺ¨λ“ˆμ„ λ§Œλ“€μ–΄μ•Όν•˜λŠ” 것은 쒋은 μ†”λ£¨μ…˜μ΄λ©° λ„ˆλ¬΄ 반볡적이라고 μƒκ°ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

이 문제λ₯Ό μ²˜λ¦¬ν•˜λŠ” 데 μ‚¬μš©ν•˜λŠ” 방법은 @ namlq93μ—μ„œ μ œμ•ˆν•œ κ²ƒμ²˜λŸΌ div μš”μ†Œλ‘œ μ‚¬μš©μž 지정 ꡬ성 μš”μ†Œλ₯Ό λž˜ν•‘ν•˜λŠ” κ²ƒμ΄μ§€λ§Œ κΉ¨λ—ν•˜μ§€ μ•Šμ€ 것 κ°™μŠ΅λ‹ˆλ‹€.

여기도 λ§ˆμ°¬κ°€μ§€μž…λ‹ˆλ‹€. λ‹€μŒκ³Ό 같은 μ‚¬μš©μž 지정 ꡬ성 μš”μ†Œλ₯Ό μ‚¬μš©ν•˜λ©΄ 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.

        <Link href="/href">
          <Button
            type="custom"
            color="#FCFCFC"
          >
             buttonText
          </Button>
        </Link>

μ΄λŠ” ꡬ성 μš”μ†Œλ₯Ό μžμ‹μœΌλ‘œ μ‚¬μš©ν•  λ•Œλ§Œ λ°œμƒν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ κ²½κ³ λ₯Ό μ œκ³΅ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

        <Link href="/href">
          <button
            type="custom"
            color="#FCFCFC"
          >
            buttonText
          </button>
        </Link>

        <Link href="/href">
          <a>
            <Button
              type="custom"
              color="#FCFCFC"
            >
              buttonText
            </Button>
          </a>
        </Link>

μž‘λ™ν•©λ‹ˆλ‹€, 친ꡬ κ°μ‚¬ν•©λ‹ˆλ‹€ !!

λΉ„μŠ·ν•œ λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€

아직 κ±°κΈ°

https://nextjs.org/docs/api-reference/next/link#if -the-child-is-a-function-component

이거 μŠ¬ν”„λ„€.

μ–Όλ§ˆμ „μ— NextJS 컨퍼런슀λ₯Όλ³΄κ³  "μ™€μš° λ„₯μŠ€νŠΈκ°€ 미래 λ‹€"라고 μƒκ°ν–ˆμŠ΅λ‹ˆλ‹€. μ €λŠ” Next와 Vercel μƒνƒœκ³„λ₯Ό 정말 μ’‹μ•„ν•˜κ³  μ†”μ§νžˆ κ·Έλ ‡κ²Œ 말할 수 있고 Next의 μ˜Ήν˜Έμžκ°€λ˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 이와 같은 λ¬Έμ œκ°€ μ’…κ²°λ˜κ³  ν•΄κ²°λ˜μ§€ μ•ŠμœΌλ©΄ κ·Έλ ‡κ²Œν•˜κΈ°κ°€ μ–΄λ ΅μŠ΅λ‹ˆλ‹€. λ‚˜λŠ” 특히 λΌμš°ν„°μ™€ κ΄€λ ¨λœ 문제 μ „μ²΄μ—μ„œ μ΄λŸ¬ν•œ μœ ν˜•μ˜ νŒ¨ν„΄μ„ μ—¬λŸ¬ 번 λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

μ‚¬μš©μž μΈ‘μ—μ„œμ΄ λ¬Έμ œμ— λŒ€ν•œ 3 가지 해결책이 있으며 그쀑 μ–΄λŠ 것도 ν›Œλ₯­ν•œ DXκ°€ μ•„λ‹™λ‹ˆλ‹€.

  1. ꢌμž₯λ˜λŠ” 방법 React.forwardRef. React.forwardRef ꡬ성 μš”μ†Œλ₯Ό λž˜ν•‘ν•©λ‹ˆλ‹€. 이것은 맀우 반볡적 일 수 μžˆμŠ΅λ‹ˆλ‹€.
  2. div , span , a λ“±κ³Ό 같은 νƒœκ·Έλ‘œ κΈ°λŠ₯ ꡬ성 μš”μ†Œλ₯Ό λž˜ν•‘ν•©λ‹ˆλ‹€.
  3. Link λŒ€μ‹  useRouterλ₯Ό 가져와 router.push

μ–΄λ–€ μ†”λ£¨μ…˜μ„ μ‚¬μš©ν•˜λ“  λͺ¨λ‘ μ΄μƒν•˜λ©°μ΄ 문제 λ˜λŠ” λ¬Έμ„œ 에 링크 된 주석이 ν•„μš”ν•˜μ—¬ λ™λ£Œ / κΈ°μ—¬μžμ—κ²Œ μ‹€μˆ˜λ‘œ 제거 / 정리λ₯Ό λ°©μ§€ν•˜λŠ” 데 ν•„μš”ν•œ 이유λ₯Ό μ„€λͺ…ν•΄μ•Όν•©λ‹ˆλ‹€.

이 λ¬Έμ œλŠ” λ…Όμ˜λ₯Ό μœ„ν•΄ μž¬κ°œλ˜μ–΄μ•Όν•œλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰