์ด์ 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.
์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
@types/react
ํจํค์ง๋ฅผ ์ฌ์ฉํด ๋ณด์๋๋ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค.Definitions by:
in index.d.ts
์ฐธ์กฐ) ๋๋ตํ๋ค.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๋ก ํ์
// ...
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
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ ์์ฒ๋ผ ํ ๋น๋ฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๊ทธ๋ ์ง ์๋ค. ๊ณ ์ ๋์ง ์์ ๊ฒฝ์ฐ์๋ ์ฌ๋ฐ๋ฅธ ์ฌ์ฉ์ ๋ณด์ฅํ๊ธฐ ์ํด ์๋์ ์ผ๋ก ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๋จ๊ฒจ๋ก๋๋ค. null์ ํ ๋นํ ์ ์์์ ๋ช ์์ ์ผ๋ก ๋ํ๋ด์ง ์๊ณ null๋ก ์ด๊ธฐํ๋ ์ฐธ์กฐ๋ React์์ ๊ด๋ฆฌํ๋ ค๋ ์ฐธ์กฐ๋ก ํด์๋ฉ๋๋ค. ์ฆ, React๋ ํ์ฌ๋ฅผ "์์ "ํ๊ณ ๋ณด๊ณ ์๋ ๊ฒ์ ๋๋ค.
null ๊ฐ์ผ๋ก ์์ํ๋ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ref ๊ฐ์ฒด๋ฅผ ์ํ๋ฉด ์ผ๋ฐ ์ธ์์๋
| null
๋ฅผ ์ง์ ํด์ผ ํฉ๋๋ค. React๊ฐ ์๋ "์์ "ํ๊ธฐ ๋๋ฌธ์ ๋ณ๊ฒฝ ๊ฐ๋ฅํฉ๋๋ค.์ด์ ์ ํฌ์ธํฐ ๊ธฐ๋ฐ ์ธ์ด๋ก ์์ฃผ ์์ ํ๊ณ ์์ ๊ถ์ด _๋งค์ฐ_ ์ค์ํ๊ธฐ ๋๋ฌธ์ ์๋ง๋ ์ด๊ฒ์ด ์ดํดํ๊ธฐ ๋ ์ฌ์ธ ๊ฒ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ์ด refs, ํฌ์ธํฐ์ธ ๊ฒ์ ๋๋ค.
.current
๋ ํฌ์ธํฐ๋ฅผ ์ญ์ฐธ์กฐํ๊ณ ์์ต๋๋ค.