Definitelytyped: [@types/react] RefObject.current๋Š” ๋” ์ด์ƒ ์ฝ๊ธฐ ์ „์šฉ์ด ์•„๋‹ˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2018๋…„ 12์›” 05์ผ  ยท  48์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: DefinitelyTyped/DefinitelyTyped

์ด์ œ ref.current ์— ํ• ๋‹นํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. https://reactjs.org/docs/hooks-faq.html#is -there-something-like-instance-variables

๊ฐ’์„ ํ• ๋‹นํ•˜๋ ค๊ณ  ํ•˜๋ฉด Cannot assign to 'current' because it is a constant or a read-only property. ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

  • [x] @types/react ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์•˜๋Š”๋ฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
  • [x] ์•ˆ์ •์ ์ธ ์ตœ์‹  ๋ฒ„์ „์˜ tsc๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. https://www.npmjs.com/package/typescript
  • [x] StackOverflow ์— ์ ํ•ฉํ•˜์ง€ ์•Š์€ ์งˆ๋ฌธ์ด ์žˆ์Šต๋‹ˆ๋‹ค. (์ ์ ˆํ•œ ์งˆ๋ฌธ์ด ์žˆ์œผ๋ฉด ๊ฑฐ๊ธฐ์—์„œ ์งˆ๋ฌธํ•˜์‹ญ์‹œ์˜ค.)
  • [x] [๋ฉ˜์…˜](https://github.com/blog/821-mention-somebody-they-re-notified) ์ž‘์„ฑ์ž( Definitions by: in index.d.ts ์ฐธ์กฐ) ๋Œ€๋‹ตํ•˜๋‹ค.

    • ์ €์ž: @johnnyreilly @bbenezech @pzavolinsky @digiguru @ericanderson @morcerf @tkrotoff @DovydasNavickas @onigoetz @ theruther4d @guilhermehubner @ferdaber @jrakotoharisoa @pascaloliv @Hotell @franklixuefei

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๊ทธ๋ ‡์ง€ ์•Š๋‹ค. ๊ณ ์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋„ ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์˜๋„์ ์œผ๋กœ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ๋‚จ๊ฒจ๋‘ก๋‹ˆ๋‹ค. null์„ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Œ์„ ๋ช…์‹œ์ ์œผ๋กœ ๋‚˜ํƒ€๋‚ด์ง€ ์•Š๊ณ  null๋กœ ์ดˆ๊ธฐํ™”๋œ ์ฐธ์กฐ๋Š” React์—์„œ ๊ด€๋ฆฌํ•˜๋ ค๋Š” ์ฐธ์กฐ๋กœ ํ•ด์„๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, React๋Š” ํ˜„์žฌ๋ฅผ "์†Œ์œ "ํ•˜๊ณ  ๋ณด๊ณ  ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

null ๊ฐ’์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ref ๊ฐœ์ฒด๋ฅผ ์›ํ•˜๋ฉด ์ผ๋ฐ˜ ์ธ์ˆ˜์—๋„ | null ๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. React๊ฐ€ ์•„๋‹Œ "์†Œ์œ "ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์ด์ „์— ํฌ์ธํ„ฐ ๊ธฐ๋ฐ˜ ์–ธ์–ด๋กœ ์ž์ฃผ ์ž‘์—…ํ–ˆ๊ณ  ์†Œ์œ ๊ถŒ์ด _๋งค์šฐ_ ์ค‘์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•„๋งˆ๋„ ์ด๊ฒƒ์ด ์ดํ•ดํ•˜๊ธฐ ๋” ์‰ฌ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์ด refs, ํฌ์ธํ„ฐ์ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. .current ๋Š” ํฌ์ธํ„ฐ๋ฅผ ์—ญ์ฐธ์กฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  48 ๋Œ“๊ธ€

PR์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค! ํ•œ์ค„๋ฐ”๊พธ๊ธฐ ์ •๋ง ์‰ฌ์šธ๊บผ์—์š” ๐Ÿ˜Š

@ํŽ˜๋ฅด๋‹ค๋ฒ ๋ฅด ,
์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” ์ด ๋ฌธ์ œ๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ์ œ๊ฐ€ ํƒ€์ดํ”„์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ฒ˜์Œ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—(๋‹จ 1์ฃผ์ผ) ์˜คํ”ˆ ์†Œ์Šค์— ๋Œ€ํ•œ ์ฒซ ๋ฒˆ์งธ ๊ธฐ์—ฌ๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

node_modules/@types/react/index.d.ts๋ฅผ ์‚ดํŽด๋ณด์•˜๊ณ  61๋ฒˆ ์ค„์— ํ˜„์žฌ๋ฅผ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ์„ ์–ธํ•˜๋Š” ๋‹ค์Œ ์ฝ”๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

interface RefObject<T> {
        readonly current: T | null;
    }

์ด๊ฒƒ์ด ๋ฌธ์ œ๋ผ๋ฉด ๋‚ด๊ฐ€ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ œ ์ฒซ PR์„ ์•ˆ๋‚ดํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?
์‹œ๊ฐ„ ๋‚ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค :)

์˜ˆ, ํ•ด๋‹น ์ค„์—์„œ readonly ์ˆ˜์ •์ž๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

React.useRef ๋Š” current ์†์„ฑ์ด readonly ๊ฐ€ ์•„๋‹Œ $ MutableRefObject $๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” ref ๊ฐœ์ฒด ์œ ํ˜•์„ ํ†ตํ•ฉํ•ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ๋“ค์€ ํ†ตํ•ฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. React ๋Ÿฐํƒ€์ž„์€ React.createRef() current ์†์„ฑ์— ์ œํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ฐ์ฒด ์ž์ฒด๋Š” ๋ด‰์ธ๋˜์ง€๋งŒ ๊ณ ์ •๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡์ง€ ์•Š๋‹ค. ๊ณ ์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋„ ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์˜๋„์ ์œผ๋กœ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ๋‚จ๊ฒจ๋‘ก๋‹ˆ๋‹ค. null์„ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Œ์„ ๋ช…์‹œ์ ์œผ๋กœ ๋‚˜ํƒ€๋‚ด์ง€ ์•Š๊ณ  null๋กœ ์ดˆ๊ธฐํ™”๋œ ์ฐธ์กฐ๋Š” React์—์„œ ๊ด€๋ฆฌํ•˜๋ ค๋Š” ์ฐธ์กฐ๋กœ ํ•ด์„๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, React๋Š” ํ˜„์žฌ๋ฅผ "์†Œ์œ "ํ•˜๊ณ  ๋ณด๊ณ  ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

null ๊ฐ’์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ref ๊ฐœ์ฒด๋ฅผ ์›ํ•˜๋ฉด ์ผ๋ฐ˜ ์ธ์ˆ˜์—๋„ | null ๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. React๊ฐ€ ์•„๋‹Œ "์†Œ์œ "ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์ด์ „์— ํฌ์ธํ„ฐ ๊ธฐ๋ฐ˜ ์–ธ์–ด๋กœ ์ž์ฃผ ์ž‘์—…ํ–ˆ๊ณ  ์†Œ์œ ๊ถŒ์ด _๋งค์šฐ_ ์ค‘์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•„๋งˆ๋„ ์ด๊ฒƒ์ด ์ดํ•ดํ•˜๊ธฐ ๋” ์‰ฌ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์ด refs, ํฌ์ธํ„ฐ์ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. .current ๋Š” ํฌ์ธํ„ฐ๋ฅผ ์—ญ์ฐธ์กฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ณตํ‰ํ•ฉ๋‹ˆ๋‹ค. ref ์†Œํ’ˆ์œผ๋กœ ์ „๋‹ฌ๋˜์ง€ ์•Š์œผ๋ฉด React์—์„œ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํฌ์ธํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๋„์šฐ๋ฏธ ํ•จ์ˆ˜๋กœ React.createRef() ๋ฅผ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ ๊ตฌ์กฐ๋กœ ๊ฐ„๋‹จํ•œ ํฌ์ธํ„ฐ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๋™์ผํ•œ ์˜ค๋ฒ„๋กœ๋“œ ๋…ผ๋ฆฌ๋ฅผ ๊ฐ–๋„๋ก createRef ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ธ์ˆ˜๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์กฐ๊ฑด๋ถ€ ์œ ํ˜• ๋ฐ˜ํ™˜์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. | null ๋ฅผ ํฌํ•จํ•˜๋ฉด MutableRefObject ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ํฌํ•จํ•˜์ง€ ์•Š์œผ๋ฉด (๋ถˆ๋ณ€) RefObject ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ strictNullTypes ๊ฐ€ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์ง€ ์•Š์€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํšจ๊ณผ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

๐Ÿค”

strictNullTypes ๊ฐ€ ํ™œ์„ฑํ™”๋œ _do_์— ๋Œ€ํ•ด ์ž˜๋ชป๋œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ๊ฐ€ ์ •๋ง ์‰ฌ์›Œ์•ผ ํ•ฉ๋‹ˆ๊นŒ?

์ด ๋ฌธ์ œ๋ฅผ ๋งŒ๋“ค ๋•Œ ์ด๋ฏธ | null ๊ณผ๋ถ€ํ•˜๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ซ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ํ”ํ•˜์ง€ ์•Š์€ ํŒจํ„ด์ด๋ผ ์ด๋Ÿฐ๊ฒŒ ์žˆ์„ ์ค„์€ ๋ชฐ๋ž๋„ค์š”. ๋ฌธ์„œ์—์„œ ์–ด๋–ป๊ฒŒ ๋†“์ณค๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ ๋งค์šฐ ์ž˜ ๋ฌธ์„œํ™”๋˜๊ณ  ์„ค๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. useRef ์™€ createRef ๋ฅผ ํ†ตํ•ฉํ•˜์ง€ ์•Š๋Š” ํ•œ ์ด๊ฒƒ์„ ๋ฌธ์ œ๊ฐ€ ์•„๋‹Œ ๊ฒƒ์œผ๋กœ ๋‹ซ์•„๋„ ์ข‹์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ ์ž์ฒด๊ฐ€ useRef ๊ฐ€ ์•„๋‹ˆ๋ผ createRef ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— $# createRef ์—์„œ ์—ญ์ฐธ์กฐ๋œ ํฌ์ธํ„ฐ ๊ฐ’์„ ์ง์ ‘ ์ˆ˜์ •ํ•˜๋Š” ์‚ฌ๋žŒ์ด ๊ฑฐ์˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฌธ์ œ๋ฅผ ๋‹ซ์•„๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

์ด ์˜ค๋ฒ„๋กœ๋“œ ํŒจํ„ด์ด ์ž˜ ๋‚˜์˜ฌ์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. ํ›„ํฌ ๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด ๊ธฐ๋ณธ๊ฐ’๊ณผ ํ•จ๊ป˜ useRef ๋ฅผ ๋ช‡ ๋ฒˆ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ .current ์˜ ๊ฐ’์€ ๊ฒฐ์ฝ” null์ด์ง€๋งŒ null์ด ์•„๋‹Œ ์–ด์„ค์…˜ ์—ฐ์‚ฐ์ž๋ฅผ ๊ณ„์† ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ํ†ต๊ณผํ•˜๋Š” ๊ฒƒ์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ผ์ข…์˜ ์„ฑ๊ฐ€์‹  ์ผ์ž…๋‹ˆ๋‹ค.

์ดˆ๊ธฐ ๊ฐ’์ด ์ฃผ์–ด์ง€๋ฉด ๋ฐ˜ํ™˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ƒ๋žตํ•˜๋ฉด ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์ด ๋” ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๊นŒ? ์ดˆ๊ธฐ ๊ฐ’์ด ์ฃผ์–ด์ง€๋ฉด ref๋Š” ์•„๋งˆ๋„ ref ๋ฅผ ํ†ตํ•ด ๊ตฌ์„ฑ ์š”์†Œ์— ์ „๋‹ฌ๋˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ฉฐ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ๋” ๋งŽ์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด์— ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ref๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ ์ดˆ๊ธฐ ๊ฐ’์ด ์ œ๊ณต๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. @Kovensky ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์„ธ์š”?

@ferdaber useRef ๋Š” | null ์™€ null ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๋Š” ์ผ๋ฐ˜ ์ธ์ˆ˜๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ํ•œ ํ•ญ์ƒ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ _๋ฐ_ nullable์ด ์•„๋‹™๋‹ˆ๋‹ค.

๊ตฌ์„ฑ ์š”์†Œ์— ์ „๋‹ฌ๋˜๋Š” ์ฐธ์กฐ๋Š” null ๋กœ ์ดˆ๊ธฐํ™”๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๊ทธ๊ฒƒ์ด ๋ฆด๋ฆฌ์Šค๋  ๋•Œ React๊ฐ€ ์ฐธ์กฐ๋ฅผ ์„ค์ •ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(์˜ˆ: ์กฐ๊ฑด๋ถ€๋กœ ๋งˆ์šดํŠธ๋œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งˆ์šดํŠธ ํ•ด์ œํ•  ๋•Œ). useRef ๊ฐ’์„ ์ „๋‹ฌํ•˜์ง€ ์•Š์œผ๋ฉด ๋Œ€์‹  undefined ์‹œ์ž‘ํ•˜๋ฏ€๋กœ ์ด์ œ | null ์‹ ๊ฒฝ ์จ์•ผ ํ•˜๋Š” ํ•ญ๋ชฉ์— | undefined ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. | null .

React ๋ฌธ์„œ์˜ ๋ฌธ์ œ์ ๊ณผ ์ดˆ๊ธฐ ๊ฐ’ ์—†์ด useRef ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ React ํŒ€์ด null ์™€ undefined ์˜ ์ฐจ์ด์— ๋Œ€ํ•ด ๋ณ„๋กœ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ Flow ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


์–ด์จŒ๋“ , ๋‚ด๊ฐ€ useRef ๋ฅผ ์ •์˜ํ•œ ๋ฐฉ์‹์€ @bschlenk ์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ์ •ํ™•ํžˆ ๋งž์Šต๋‹ˆ๋‹ค. ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ์ด์œ ๋กœ null ๋Š” "์ƒ๋žต๋œ" ๊ฐ’๋ฟ์ž…๋‹ˆ๋‹ค.

์•„, ์ž์„ธํžˆ ๋ณด๋ฉด ์•Œ๊ฒ ์ง€๋งŒ, ๋ฆฌ์•กํŠธ ์†Œ์Šค์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜ ์—†์ด undefined ๋กœ ์ดˆ๊ธฐํ™”๋˜๋Š” ๊ฒƒ๋„ ํฅ๋ฏธ๋กญ๋‹ค. ์ฟจํ•ด์„œ ๋ชจ๋“  ๊ฒƒ์ด ๋ณต์ˆญ์•„์ฒ˜๋Ÿผ ๋“ค๋ฆฐ๋‹ค. ๐Ÿ‘

์žˆ๋Š” ๊ทธ๋Œ€๋กœ๋Š” ๊ดœ์ฐฎ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. | null ๋ฅผ ํฌํ•จํ•˜๋Š”์ง€ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด current ์œ ํ˜•์ด ์—ฌ์ „ํžˆ null์ผ ์ˆ˜ ์žˆ๊ณ  ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ๋งŒ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค๋Š” ์ ์ด ์กฐ๊ธˆ ์ด์ƒํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ React ๋ฌธ์„œ๋Š” ํ•ญ์ƒ ๋ช…์‹œ์ ์œผ๋กœ null์„ ์ „๋‹ฌํ•˜๋ฏ€๋กœ initialValue๋ฅผ ์ƒ๋žตํ•˜๋Š” ๊ฒƒ์ด ์œ ํšจํ•œ๊ฐ€์š”?

์ผ๋ฐ˜์ ์œผ๋กœ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉฐ, ์ ์–ด๋„ ๊ณผ๊ฑฐ์— ๋‚ด๊ฐ€ ์–ด๋–ค ๋ฌธ์„œ์—์„œ React ํŒ€์ด "์ž‘๋™ํ•˜๋”๋ผ๋„" ์ƒ๋žตํ•  ์˜๋„๊ฐ€ ์—†๋‹ค๊ณ  ์ง€์ ํ–ˆ์„ ๋•Œ ์ง€์ ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด createContext ์— ๋Œ€ํ•œ ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๊ฐ€ ํ•„์š”ํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ปจํ…์ŠคํŠธ๋ฅผ undefined ๋กœ ์‹œ์ž‘ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ undefined ๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ถ€ ์šฉ๋„์—์„œ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

https://reactjs.org/docs/hooks-faq.html#is -there-something-like-instance-variables
https://reactjs.org/docs/hooks-faq.html#how -to-get-the-previous-props-or-state
https://reactjs.org/docs/hooks-faq.html#how -to-read-an-often-change-value-from-usecallback

@ferdaber ๊ทธ๊ฒƒ์€ ์œ ํ˜•์— ๋Œ€ํ•ด ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. useRef() (์ธ์ˆ˜ ์—†์Œ)์˜ current ์œ ํ˜•์€ ๋ฌด์—‡์ด์–ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? undefined ? any ? ๊ทธ๊ฒƒ์ด ๋ฌด์—‡์ด๋“ , ์ผ๋ฐ˜ ์ธ์ˆ˜๋ฅผ ์ œ๊ณตํ•˜๋”๋ผ๋„ | undefined ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. _๊ทธ๋ฆฌ๊ณ _ ๋ฐ˜์‘ ์š”์†Œ ์ฐธ์กฐ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ฐธ์กฐ์ธ ๊ฒฝ์šฐ(๋‹จ์ˆœํžˆ ์Šค๋ ˆ๋“œ ๋กœ์ปฌ ์ €์žฅ์†Œ๊ฐ€ ์•„๋‹ˆ๋ผ) | null ๋„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. React๊ฐ€ ๊ฑฐ๊ธฐ์— null ๋ฅผ ์“ธ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ด์ œ current ์ด $#$ T T | null | undefined $ ์ž„์„ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

// you should always give an argument even if the docs sometimes miss them
// $ExpectError
const ref1 = useRef()
// this is a mutable ref but you can only assign `null` to it
const ref2 = useRef(null)
// this is also a mutable ref but you can only assign `undefined`
const ref3 = useRef(undefined)
// this is a mutable ref of number
const ref4 = useRef(0)
// this is a mutable ref of number | null
const ref5 = useRef<number | null>(null)
// this is a mutable ref with an object
const ref6 = useRef<React.CSSProperties>({})
// this is a mutable ref that can hold an HTMLElement
const ref7 = useRef<HTMLElement | null>(null)
// this is the only case where the ref is immutable
// you did not say in the generic argument you want to be able to write
// null into it, but you gave a null anyway.
// I am taking this as the sign that this ref is intended
// to be used as an element ref (i.e. owned by React, you're only sharing)
const ref8 = useRef<HTMLElement>(null)
// not allowed, because you didn't say you want to write undefined in it
// this is essentially what would happen if we allowed useRef with no arguments
// to make it worse, you can't use it as an element ref, because
// React might write a null into it anyway.
// $ExpectError
const ref9 = useRef<HTMLElement>(undefined)

์˜ˆ, ์ด DX๋Š” ์ €์—๊ฒŒ ์ ํ•ฉํ•˜๊ณ  ๋ฌธ์„œ๋Š” A++์ด๋ฏ€๋กœ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์ด ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ํ˜ผ๋™ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํžˆ ์„ค๋ช…ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ์†”์งํžˆ typedoc์—์„œ ์ด ๋ฌธ์ œ๋ฅผ ์˜๊ตฌ ๋งํฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. :)

useRef<T>() useRef<T | undefined>(undefined) ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๊ฒƒ์œผ๋กœ ๋งŒ๋“  ref๋Š” ์—ฌ์ „ํžˆ ์Šค๋ ˆ๋“œ ๋กœ์ปฌ ์ €์žฅ์†Œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์š”์†Œ ref๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š”... ํ—ˆ์šฉ๋˜๋Š” ์ผ๋ฐ˜ ์ธ์ˆ˜๋ฅผ _ํ•˜์ง€ ์•Š๋Š”_ ๊ฒฝ์šฐ ์–ด๋–ป๊ฒŒ ๋ฉ๋‹ˆ๊นŒ? TypeScript๋Š” {} ๋งŒ ์ถ”๋ก ํ•ฉ๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅธ ๊ธฐ๋ณธ ์œ ํ˜•์€ unknown ์ด์ง€๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์ฝ”๋“œ์—์„œ ์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

~~~js
// ...
IntervalRef = useRef๋กœ ํ•˜์ž(์—†๋Š”); // let ๋Œ€์‹  const๋กœ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค.
// ...
useEffect(() => {
const ๊ฐ„๊ฒฉ = setInterval( () => { /* ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•˜์‹ญ์‹œ์˜ค */}, 1000);
intervalRef.current = ๊ฐ„๊ฒฉ; // ์ด ์ค„์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

return () => {
    clearInterval(intervalRef.current);
}

})
// ...
~์—ฌ๊ธฐ์—์„œ readonly ๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.~ js
์ธํ„ฐํŽ˜์ด์Šค ์ฐธ์กฐ ๊ฐœ์ฒด{
์ฝ๊ธฐ ์ „์šฉ ์ „๋ฅ˜: T | ์—†๋Š”;
}
~~~

๋‚˜๋Š” reack ํ›„ํฌ์™€ typescript๋ฅผ ๋ชจ๋‘ ์‚ฌ์šฉํ•˜๋Š” ์ƒˆ๋กœ์šด ์‚ฌ๋žŒ์ด๋ฏ€๋กœ(๊ทธ๋ƒฅ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ๋งŒ ํ•˜๋ฉด ๋จ) ๋‚ด ์ฝ”๋“œ๊ฐ€ ํ‹€๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ null ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ฐธ์กฐ๋ฅผ ๋งŒ๋“ค๊ณ  ์ผ๋ฐ˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•˜๋ฉด React๊ฐ€ ์ฐธ์กฐ๋ฅผ "์†Œ์œ "ํ•˜๋„๋ก ํ•˜๋ ค๋Š” ์˜๋„๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž์‹ ์ด ์†Œ์œ ํ•œ ref๋ฅผ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

const intervalRef= useRef<NodeJS.Timeout | null>(null) // <-- the generic type is NodeJS.Timeout | null

@ferdaber ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

์—ฌ๊ธฐ์„œ ํ•œ ๋‹จ๊ณ„ ๋” ๋‚˜์•„๊ฐ€ current ์˜ ๋ฐ˜ํ™˜ ์œ ํ˜•์„ ์‚ดํŽด๋ณด๋ฉด T | null T ์—ฌ์•ผ ํ• ๊นŒ์š”? ํ›„ํฌ์˜ ์ถœํ˜„์œผ๋กœ ์šฐ๋ฆฌ๋Š” ๋ชจ๋“  ์ฐธ์กฐ๊ฐ€ null ์ผ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ _ํ•ญ์ƒ ๊ทธ๋Ÿฐ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค_, ํŠนํžˆ useRef ๊ฐ€ null์ด ์•„๋‹Œ ์ด๋‹ˆ์…œ๋ผ์ด์ €์™€ ํ•จ๊ป˜ ํ˜ธ์ถœ๋˜๋Š” ๋นˆ๋ฒˆํ•œ ๊ฒฝ์šฐ์— ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์ž‘์„ฑํ•˜๋Š” ๊ฒฝ์šฐ https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31065#issuecomment -446660394์˜ ํ›Œ๋ฅญํ•œ ์˜ˆ์ œ ๋ชฉ๋ก์—์„œ ๊ณ„์† ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

const numericRef = useRef<number>(42);

numericRef.current ์˜ ์œ ํ˜•์€ ๋ฌด์—‡์ด์–ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? number | null ํ•„์š”๋Š” _ํ•„์š”_ ์—†์Šต๋‹ˆ๋‹ค.

์œ ํ˜•๊ณผ ๊ธฐ๋Šฅ์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜ํ–ˆ๋‹ค๋ฉด:

interface RefObject<T> {
  current: T;
}

function useRef<T>(initialValue: T): RefObject<T>;
function useRef<T>(initialValue: T|null): RefObject<T | null>;

function createRef<T>(): RefObject<T | null>;

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‚ฌ์šฉ๋ฒ•๊ณผ ์œ ํ˜•์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

const r1 = useRef(42);
// r1 is of type RefObject<number>
// r1.current is of type number (not number | null)

const r2 = useRef<number>(null);
// r2 is of type RefObject<number | null>
// r2.current is of type number | null

const r3 = useRef(null);
// r3 is of type RefObject<null>
// r3.current is of type null

const r4 = createRef<number>();
// r4 is of type RefObject<number | null>
// r4.current is of type number | null

๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

React ํŒ€์— ๋”ฐ๋ฅด๋ฉด "๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋˜์ง€ ์•Š์€ useRef ์˜ ์œ ํ˜•์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?"์— ๋Œ€ํ•œ ๋‹ต๋ณ€์€ ํ•ด๋‹น ํ˜ธ์ถœ(๋ฌธ์„œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ )์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

DOM/์ปดํฌ๋„ŒํŠธ ์ฐธ์กฐ์— ๋Œ€ํ•œ ํŽธ์˜ ์˜ค๋ฒ„๋กœ๋“œ๋กœ |null _specifically_ ์˜ค๋ฒ„๋กœ๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ํ•ญ์ƒ null์„ ์‹œ์ž‘ํ•˜๊ณ  ๋งˆ์šดํŠธ ํ•ด์ œ ์‹œ ํ•ญ์ƒ null๋กœ ์žฌ์„ค์ •๋˜๋ฉฐ ํ˜„์žฌ ์‚ฌ์šฉ์ž ์ž์‹ ์„ ์žฌํ• ๋‹นํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์˜ค์ง React๋ฟ์ž…๋‹ˆ๋‹ค.

์ฝ๊ธฐ ์ „์šฉ์€ ์ง„์ •ํ•œ JavaScript ๊ณ ์ • ๊ฐ์ฒด/๊ฒŒํ„ฐ ์ „์šฉ ์†์„ฑ์˜ ํ‘œํ˜„๋ณด๋‹ค ๋…ผ๋ฆฌ ์˜ค๋ฅ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋” ๋งŽ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด์จŒ๋“  ๊ฐ’์„ null๋กœ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋™์•ˆ null์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ผ๋ฐ˜ ์ธ์ˆ˜๋ฅผ ๋‘˜ ๋‹ค ์ œ๊ณตํ•  ๋•Œ๋งŒ ์šฐ์—ฐํžˆ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒฝ์šฐ๋Š” ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์•„, ์˜ˆ, ์ด์ œ RefObject<T> MutableRefObject<T> ์—์„œ ์ด๋ฏธ | null ์ผ€์ด์Šค๊ฐ€ ์ œ๊ฑฐ๋˜์—ˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ useRef<number>(42) ์ผ€์ด์Šค๋Š” ์ด๋ฏธ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์„ค๋ช… ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

createRef ๋กœ ๋ฌด์—‡์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? ์ง€๊ธˆ ๋‹น์žฅ์€ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” RefObject<T> ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์šฐ๋ฆฌ ์ฝ”๋“œ๋ฒ ์ด์Šค์— ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” (๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ) useRef ref ๊ฐœ์ฒด์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. createRef ํƒ€์ดํ•‘์„ ์กฐ์ •ํ•˜์—ฌ ๊ฐ€๋ณ€ ref ๊ฐ์ฒด๋ฅผ ํ˜•์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

(๊ทธ๋ฆฌ๊ณ  ref ์†์„ฑ์€ RefObject<T> Ref<T> ์œ ํ˜•์œผ๋กœ ์ •์˜๋˜์–ด ๋ชจ๋“  ๊ฒƒ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ๋ฆฌ์—๊ฒŒ ํฐ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. useRef ์ค‘ ref , ์šฐ๋ฆฌ๋Š” forwardRef ํ˜ธ์ถœ์„ ํ†ตํ•ด ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์‚ฌ์‹ค์„ ์ด์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.)

ํ ... ์•„๋งˆ๋„ ์šฐ๋ฆฌ๋Š” ์ธ์ˆ˜๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์—(ํ•ญ์ƒ null๋กœ ์‹œ์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์—) ์กฐ๊ฑด๋ถ€ ์œ ํ˜•์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋™์ผํ•œ ํŠธ๋ฆญ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

: null extends T ? MutableRefObject<T> : RefObject<T> ๋Š” ๋™์ผํ•œ ๋…ผ๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. null์„ ๋„ฃ๊ณ  ์‹ถ๋‹ค๊ณ  ๋งํ•˜๋ฉด ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํ˜„์žฌ ์˜๋ฏธ์—์„œ ์—ฌ์ „ํžˆ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์•„์ฃผ ์ข‹์€ ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค. createRef ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— $ | null ์˜ต์…˜์„ ํ•ญ์ƒ ํฌํ•จํ•ด์•ผ ํ•˜๋ฏ€๋กœ ( useRef ์™€ ๋‹ฌ๋ฆฌ) MutableRefObject<T | null> ๋ผ๊ณ  ํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋‘˜ ๋‹ค TS์—์„œ ์ผํ•˜๊ฒŒ ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ TS ํ”Œ๋ ˆ์ด๊ทธ๋ผ์šด๋“œ๋กœ ๊ตฌ์„ฑ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
https://tinyurl.com/y75c32y3

์œ ํ˜•์€ ํ•ญ์ƒ MutableRefObject ๋กœ ๊ฐ์ง€๋ฉ๋‹ˆ๋‹ค.

forwardRef ๋กœ ๋ฌด์—‡์„ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์„ธ์š”? ref ๋ฅผ Ref<T> ๋กœ ์„ ์–ธํ•˜๋ฉฐ, ์—ฌ๊ธฐ์—๋Š” MutableRefObject ๊ฐ€๋Šฅ์„ฑ์ด ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

(์–ด๋ ค์›€์„ ์œ ๋ฐœํ•˜๋Š” ์šฐ๋ฆฌ์˜ ์œ ์Šค ์ผ€์ด์Šค๋Š” ๊ธฐ๋Šฅ์  ref ๋˜๋Š” ref ๊ฐ์ฒด๊ฐ€ ๋  ์ˆ˜ ์žˆ๋Š” ref์˜ ๋ฐฐ์—ด์„ ์ทจํ•˜๊ณ  ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ๋Š” ๋‹จ์ผ ๊ฒฐํ•ฉ๋œ ref [a functional ref]๋ฅผ ์ƒ์„ฑํ•˜๋Š” mergeRefs ํ•จ์ˆ˜์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ฒฐํ•ฉ๋œ ref๊ฐ€ ๊ธฐ๋Šฅ์  ref์ธ ๊ฒฝ์šฐ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ ref ๊ฐœ์ฒด์ธ ๊ฒฝ์šฐ .current ๋ฅผ ์„ค์ •ํ•˜์—ฌ ์ œ๊ณต๋œ ๋ชจ๋“  ์ฐธ์กฐ์— ๋“ค์–ด์˜ค๋Š” ์ฐธ์กฐ ์š”์†Œ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. RefObject<T> ๋ถˆ๋ณ€์ด๊ณ  MutableRefObject<T> in Ref<T> ๊ฐ€ ํฌํ•จ๋˜์ง€ ์•Š์œผ๋ฉด ๊ทธ๊ฒŒ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. forwardRef์™€ Ref์— ๋Œ€ํ•ด ๋ณ„๋„์˜ ๋ฌธ์ œ๋ฅผ ์ œ๊ธฐํ•ด์•ผ ํ• ๊นŒ์š”?์–ด๋ ค์›€?)

์œ„์—์„œ ์„ค๋ช…ํ•œ ์ด์œ ๋กœ useRef ์˜ ์œ ํ˜•์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค( createRef ๋Š” ์•„์ง ๋…ผ์˜ ์ค‘์ž„). ๊ทธ ๊ทผ๊ฑฐ์— ๋Œ€ํ•ด ์งˆ๋ฌธ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31065#issuecomment -457650501์—์„œ ๋‹ค๋ฃจ๋Š” ํ•ญ๋ชฉ์— ๋Œ€ํ•ด ๋ณ„๋„์˜ ๋ฌธ์ œ๋ฅผ ์ œ๊ธฐํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

์˜ˆ, ๋ถ„๋ฆฌํ•ฉ์‹œ๋‹ค.

null ๊ฐ’์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ref ๊ฐœ์ฒด๋ฅผ ์›ํ•˜๋ฉด ์ผ๋ฐ˜ ์ธ์ˆ˜์—๋„ | null ๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. React๊ฐ€ ์•„๋‹Œ "์†Œ์œ "ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! useRef ์ผ๋ฐ˜์— null์„ ์ถ”๊ฐ€ํ•˜๋ฉด ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ „์—

const ref = useRef<SomeType>(null) 

// Later error: Cannot assign to 'current' because it is a constant or a read-only property.

ํ›„์—

const ref = useRef<SomeType | null>(null)

forwardRef ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•œ ๋˜ ๋‹ค๋ฅธ ์˜๊ฒฌ์ด ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๊นŒ? ๊ธฐ๋ณธ์ ์œผ๋กœ ref๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ํ˜„์žฌ ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋Š” ref๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์š”์ ์˜ ์ผ๋ถ€๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ํ›„ํฌ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

export const useCombinedRefs = <T>(...refs: Ref<T>[]) =>
    useCallback(
        (element: T) =>
            refs.forEach(ref => {
                if (!ref) {
                    return;
                }

                if (typeof ref === 'function') {
                    ref(element);
                } else {
                    ref.current = element; // this line produces error
                }
            }),
        refs,
    );

๊ทธ๋ฆฌ๊ณ  ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. "'ํ˜„์žฌ'๋Š” ์ฝ๊ธฐ ์ „์šฉ ์†์„ฑ์ด๋ฏ€๋กœ ํ• ๋‹นํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."
current ๋ฅผ writeable๋กœ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์†์ž„์ˆ˜๋ฅผ ์จ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

(ref.current as React.MutableRefObject<T> ).current = element;

์˜ˆ, ์ด๊ฒƒ์€ ์•ฝ๊ฐ„ ๊ฑด์ „ํ•˜์ง€ ์•Š์ง€๋งŒ ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ํ• ๋‹น์ด ์šฐ์—ฐ์ด ์•„๋‹Œ ๊ณ ์˜์ ์ธ ๊ฒฝ์šฐ๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์ผํ•œ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. React์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ๋ณต์ œํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ๊ทœ์น™์„ ์œ„๋ฐ˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋™์ผํ•œ ์˜ค๋ฒ„๋กœ๋“œ ๋…ผ๋ฆฌ๋ฅผ ๊ฐ–๋„๋ก createRef ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ธ์ˆ˜๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์กฐ๊ฑด๋ถ€ ์œ ํ˜• ๋ฐ˜ํ™˜์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. | null ๋ฅผ ํฌํ•จํ•˜๋ฉด MutableRefObject ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ํฌํ•จํ•˜์ง€ ์•Š์œผ๋ฉด (๋ถˆ๋ณ€) RefObject ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

์ •๋ง ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

(ref.current as React.MutableRefObject<T>).current = element;

ํ•ด์•ผํ•œ๋‹ค:

(ref as React.MutableRefObject<T>).current = element;

React์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ๋ณต์ œํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ ๋ฌธ์„œ ๊ฐ€ ๊ตฌ์‹์ด๋ผ๋Š” ๋œป์ธ๊ฐ€์š”? ๋‚ด๋ถ€ ๋™์ž‘์ด ์•„๋‹ˆ๋ผ ์˜๋„๋œ ์›Œํฌํ”Œ๋กœ๋กœ ๋ช…ํ™•ํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ ๋ฌธ์„œ๋Š” ๊ท€ํ•˜๊ฐ€ ์†Œ์œ ํ•œ ์ฐธ์กฐ๋ฅผ ์ฐธ์กฐํ•˜์ง€๋งŒ HTML ์š”์†Œ์— ref ์†์„ฑ์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ์ฐธ์กฐ์˜ ๊ฒฝ์šฐ _๋‹น์‹ ์—๊ฒŒ_ ์ฝ๊ธฐ ์ „์šฉ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

function Component() {
  // same API, different type semantics
  const countRef = useRef<number>(0); // not readonly
  const divRef = useRef<HTMLElement>(null); // readonly

  return <button ref={divRef} onClick={() => countRef.current++}>Click me</button>
}

๋‚ด ๋‚˜์œ, ๋” ์Šคํฌ๋กคํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์†Œ์œ ํ•œ ์ฐธ์กฐ์— ๋Œ€ํ•ด readonly ์— ๋Œ€ํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์œผ๋ฉฐ ๋™์ผํ•œ ๊ฒฝ์šฐ๋ผ๊ณ  ๊ฐ€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. (์ง€๊ธˆ์€ ๋‹ค๋ฅธ ์ž‘์—… ํ๋ฆ„์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๋ถˆํ–‰ํžˆ๋„ ๋” ์ด์ƒ ์˜ค๋ฅ˜๋ฅผ ์žฌํ˜„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค...)

์•„๋ฌดํŠผ ์„ค๋ช… ์ •๋ง ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

์ฃผ์ œ์˜ createRef ๋ถ€๋ถ„์ด ์ด๋™ํ–ˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ ์—ฌ๊ธฐ์—๋„ ๊ฒŒ์‹œํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

React Native(React Navigation)์šฉ์œผ๋กœ ์ธ๊ธฐ ์žˆ๋Š” ํƒ์ƒ‰ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์„œ์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ createRef ๋ฅผ ํ˜ธ์ถœํ•œ ๋‹ค์Œ ref๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์ด React๊ฐ€ ๊ทธ๊ฒƒ๋“ค์„ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋ผ๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค(DOM์ด ์—†์Šต๋‹ˆ๋‹ค).

React Native์˜ ์œ ํ˜•์ด ๋‹ฌ๋ผ์•ผ ํ•ฉ๋‹ˆ๊นŒ?

์ฐธ์กฐ: https://reactnavigation.org/docs/navigating-without-navigation-prop

@sylvanaar
ํƒ์ƒ‰์„ ์ดˆ๊ธฐํ™”ํ•  ๋•Œ๋„ ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ฐพ์œผ์…จ์Šต๋‹ˆ๊นŒ?

๋ฐฉ๊ธˆ ์ฝ์€ ๋‚ด์šฉ ์š”์•ฝ: createRef<T> ์— ์˜ํ•ด ์ƒ์„ฑ๋œ ref์— ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ์บ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์ด ๊ฒฝ์šฐ readonly ๋Š” ์‹ค์ œ๋กœ ref์— ๋Œ€ํ•œ ๊ฐ’ ์„ค์ •์„ ์ „ํ˜€ ๋ฐฉ์ง€ํ•˜๋ฏ€๋กœ ํ•จ์ˆ˜์˜ ์ „์ฒด ๋ชฉ์ ์„ ๋ฌดํšจํ™”ํ•ฉ๋‹ˆ๋‹ค.

TLDR: ์ดˆ๊ธฐ ๊ฐ’์ด null (์„ธ๋ถ€ ์ •๋ณด: ๋˜๋Š” ์œ ํ˜• ๋งค๊ฐœ๋ณ€์ˆ˜ ์™ธ๋ถ€์˜ ๋‹ค๋ฅธ ๊ฐ’)์ธ ๊ฒฝ์šฐ ์œ ํ˜• ๋งค๊ฐœ๋ณ€์ˆ˜์— | null ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด .current ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ •์ƒ์ฒ˜๋Ÿผ ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰