ํฌ์ŠคํŠธ

๐ŸŒ’ React Native ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ - Context

๐Ÿ’ซ Context


@ U ๊ธฐ๋ง๊ณ ์‚ฌ ์ถœ์ œ : Context, 306p, useToggleTheme, useContext

์ปดํฌ๋„ŒํŠธ์˜ ์†์„ฑ์€ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ์–ด๋–ค ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ง๊ณ„ ์ž์‹์ด ์•„๋‹Œ ์†์ž๋‚˜ ์ค‘์†์ž ์ปดํฌ๋„ŒํŠธ์— ์†์„ฑ์„ ์ „๋‹ฌํ•˜๋ ค๊ณ  ํ•˜๋ฉด โ€˜์ง€์†์ ์ธ ์†์„ฑ ์ „๋‹ฌโ€™์„ ํ•ด์•ผ ํ•œ๋‹ค. (๋น„ํšจ์œจ์ )

1
2
3
4
5
<์ž์‹์ปดํฌ๋„ŒํŠธ shared_props={shared_props} />
({shared_props}) => <์†์ž์ปดํฌ๋„ŒํŠธ shared_props={shared_props} />
({shared_props}) => <์ฆ์†์ž์ปดํฌ๋„ŒํŠธ shared_props={shared_props} />

// shared_props๋ฅผ ๋‹จ์ง€ ์ฆ์†์ž ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ์“ฐ๋”๋ผ๋„ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์™€ ์†์ž ์ปดํฌ๋„ŒํŠธ ๋ชจ๋‘์—๊ฒŒ ์†์„ฑ์„ ์ „๋‹ฌํ•ด์•ผ๋งŒ ํ•จ

์ด๋Ÿฐ ์†์„ฑ ์ „๋‹ฌ์„ ๋Œ€์‹ ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์ด ์ปจํ…์ŠคํŠธ์ด๋‹ค.

์ปจํ…์ŠคํŠธ๋Š”, react ํŒจํ‚ค์ง€์—์„œ ์ œ๊ณตํ•˜๋Š” createContext์™€ useContext ํ›…์„ ํ†ตํ•ด ์ด๋ฃจ์–ด์ง„๋‹ค.

createContext ํ•จ์ˆ˜ ํ˜ธ์ถœ๋กœ ์–ป์€ ๊ฐ’์ด ์ปจํ…์ŠคํŠธ๋‹ค.

1
2
3
4
<Provider value={} />  // ๋ถ€๋ชจ, by createContext
useContext ~ // ์ž์‹
useContext ~ // ์†์ž
useContext ~ // ์ฆ์†์ž

์ปจํ…์ŠคํŠธ๋ฅผ ์“ฐ๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” ์ด๋ฆ„์— โ€˜Providerโ€™๋ฅผ, ์ปค์Šคํ…€ ํ›…์—๋Š” ์ด๋ฆ„์— โ€˜use~โ€™๋ฅผ ์“ด๋‹ค.

์ปจํ…์ŠคํŠธ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•œ react-native-paper์™€ ๊ฐ™์€ ํŒจํ‚ค์ง€ ๋˜ํ•œ โ€˜Providerโ€™ ๊ฐ€ ๋“ค์–ด๊ฐ„ ์ปดํฌ๋„ŒํŠธ์™€ Provider๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” useTheme์™€ ๊ฐ™์€ ์ปค์Šคํ…€ ํ›…์„ ์ œ๊ณตํ•œ๋‹ค.

๐Ÿ’ซ Theme


๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ์—์„œ ํ…Œ๋งˆ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ ค๋ฉด ๋ฐ˜๋“œ์‹œ ์ปจํ…์ŠคํŠธ๋ฅผ ์ด์šฉํ•ด์•ผ ํ•œ๋‹ค.

react-native-paper ํŒจํ‚ค์ง€๋Š” Provider, AppearanceProvider ์ปดํฌ๋„ŒํŠธ์™€ useColorScheme ์ปค์Šคํ…€ ํ›…์„ ์ œ๊ณตํ•œ๋‹ค.

๋ฆฌ์•กํŠธ / ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ์—์„œ ์ œ๊ณต์ž๋ฅผ ๋œปํ•˜๋Š” โ€˜Providerโ€™๊ฐ€ ๋“ค์–ด๊ฐ„ ์ปดํฌ๋„ŒํŠธ๋Š” ํ•ญ์ƒ ์ตœ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ (Root Component)๋กœ ๋™์ž‘ํ•ด์•ผ ํ•œ๋‹ค.

์ด๋Ÿฐ ์ปดํฌ๋„ŒํŠธ๋Š” ์ฝ˜ํ…์ŠคํŠธ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋งŒ๋“ ๋‹ค.

โ€˜Providerโ€™ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ณตํ•˜๋Š” ํŒจํ‚ค์ง€๋Š” ํ•ญ์ƒ ์ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก โ€˜use~โ€™ ํ˜•ํƒœ์˜ ์ปค์Šคํ…€ ํ›…์„ ์ œ๊ณตํ•œ๋‹ค.

(AppearanceProvider๋Š” useColorScheme ์ปค์Šคํ…€ ํ›…์„ ์ œ๊ณตํ•œ๋‹ค.)

1
const scheme = useColorScheme() // 'dark' or 'light'

useColorScheme๋Š” ํ˜„์žฌ ํฐ์ด ๋‹คํฌ๋ชจ๋“œ๋กœ ๋™์ž‘ํ•˜๊ณ  ์žˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•œ๋‹ค.

useColorScheme๋Š” ๋‹จ์ˆœํžˆ ๋ชจ๋“œ๋งŒ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด๊ณ , ์‹ค์ œ๋กœ ๋ชจ๋“œ์— ๋”ฐ๋ผ ๋ฐ”ํƒ•์ƒ‰๊ณผ ๊ธ€์ž ์ƒ‰์„ ๋ฐ”๊พธ๋ ค๋ฉด ๋˜ ๋‹ค๋ฅธ โ€˜Providerโ€™ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

1
import {Provider as ํŠน์ •์ด๋ฆ„} from 'react-native-paper'

Provider๋Š” ๋„ˆ๋ฌด ์ผ๋ฐ˜์ ์ธ ์ด๋ฆ„์ด๋ผ, ํŠน์ • ์ด๋ฆ„์œผ๋กœ ๋ฐ”๊ฟ” ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

Provider๋Š” ๋ฐ˜๋“œ์‹œ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ๋™์ž‘ํ•ด์•ผ ํ•˜๋ฉฐ, ์ด๋•Œ ์„œ๋กœ ๋‹ค๋ฅธ Provider๋ฅผ ์ค‘์ฒฉ์‹œ์ผœ์•ผ ํ•  ๋•Œ ์ˆœ์„œ๋Š” ์ž์œ ๋กญ๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ปจํ…์ŠคํŠธ ๊ธฐ๋Šฅ์€ ์™„์ „ํžˆ ๋…๋ฆฝ์ ์œผ๋กœ ๋™์ž‘ํ•˜๊ธฐ์—, ๋‹ค๋ฅธ ์ปจํ…์ŠคํŠธ ๊ธฐ๋Šฅ์— ์ „ํ˜€ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Provider๋Š” theme ๋ผ๋Š” ์„ ํƒ ์†์„ฑ์„ ์ œ๊ณตํ•˜๋Š”๋ฐ, ์ด๋Š” react-native-paper ํŒจํ‚ค์ง€์—์„œ ์ œ๊ณตํ•˜๋Š” DefaultTheme, DarkTheme ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
const theme = useTheme()
const {fonts, colors} = theme

useTheme ์ปค์Šคํ…€ ํ›…์€ Provider์˜ theme ์†์„ฑ์— ์„ค์ •๋œ ๊ฐ’์„ ์ปจํ…์ŠคํŠธ๋กœ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

theme ๊ฐ์ฒด์— ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น ๊ตฌ๋ฌธ์„ ์ ์šฉํ•˜์—ฌ fonts์™€ colors ์†์„ฑ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
type SomeProps =
{
	theme: any
}

const Some: FC<SomeProps> = ({theme}) => {}

์›๋ž˜ ๊ฐ™์œผ๋ฉด ์œ„ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•˜๊ณ , ์†์„ฑ์„ ๋„˜๊ฒจ ๋ฐ›์•„ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ๋‹ค.

1
2
3
export type ContextType = {  /*๊ณต์œ  ์†์„ฑ*/ }
const defaultContextType: ContextType = { /* ๊ณต์œ  ์†์„ฑ ์ดˆ๊นƒ๊ฐ’ */ }
const SomeContext = createContext<ContextType>(defaultContextType)

์ปจํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ฐ€์žฅ ๋จผ์ € ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•˜๊ณ , ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด๋Š” createContext๋ฅผ ํ†ตํ•ด ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

createContext๋ฅผ ํ†ตํ•ด ๋งŒ๋“  ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด๋Š” Provider์™€ Consumer ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

Provider๋Š” ์•ž์„œ ์–ธ๊ธ‰ํ•œ Provider๋“ค๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ณ , Consumer๋Š” Provider๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋ฅผ ์œ„ํ•œ ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.

์ฐธ๊ณ  : ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ

Provider ์ปดํฌ๋„ŒํŠธ๋Š” value์™€ children ์†์„ฑ์ด ์žˆ๋Š” ProviderProps ์†์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค.

1
2
3
4
5
6
7
8
/* ํƒ€์ž… ๋ณ€์ˆ˜ T == createContext<T> */
interface ProviderProps<T>
{
	/* ์ปจํ…์ŠคํŠธ Provider๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ */
	value: T;
	/* ์ปดํฌ๋„ŒํŠธ์˜ children๊ณผ ๊ฐ™์€ ์˜๋ฏธ */
	children?: ReactNode;
}

react ํŒจํ‚ค์ง€๊ฐ€ ์ œ๊ณตํ•˜๋Š” useContext ํ›…์€, ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›์€ ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด๊ฐ€ ์ œ๊ณตํ•˜๋Š” Provider ์ปดํฌ๋„ŒํŠธ์˜ value ์†์„ฑ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ›…์ด๋‹ค.

useContext ํ›…์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ ํŒจํ„ด์€ ์•„๋ž˜์™€ ๊ฐ™์œผ๋ฉฐ, useColorScheme, useTheme ์ปค์Šคํ…€ ํ›…๋„ ์ด๋Ÿฐ ์ฝ”๋“œ ํŒจํ„ด์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ ์ปค์Šคํ…€ ํ›…์ด๋‹ค.

1
2
3
4
5
export const useSome = () =>
{
	const value = uesContext(SomeContext)
	return value;
}

@ TODO : 322p Switch

๐Ÿ’ซ useRef, useImperativeHandle


@ U ๊ธฐ๋ง๊ณ ์‚ฌ ์ถœ์ œ : useRef, 306p

useRef์™€ useImperativeHandle ํ›…์€ ref ์†์„ฑ์— ์ ์šฉํ•˜๋Š” ๊ฐ’์„ ๋งŒ๋“œ๋Š” ํ›…์ด๋‹ค.

๋ฆฌ์•กํŠธ์™€ ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ, App ๊ฐ™์€ ์‚ฌ์šฉ์ž ์ปดํฌ๋„ŒํŠธ์—๋Š” ๋ชจ๋‘ ref ์†์„ฑ์ด ์žˆ๋‹ค.

์ฝ”์–ด ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ref์†์„ฑ์ด ์žˆ๋Š” ์‚ฌ์šฉ์ž ์ปดํฌ๋„ŒํŠธ๋Š” forwardRef ํ•จ์ˆ˜๋กœ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค๋Š” ์กฐ๊ฑด์ด ์žˆ๋‹ค.

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

๐Ÿซง ref ์†์„ฑ

๋ฆฌ์•กํŠธ/๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ์—์„œ ์ œ๊ณตํ•˜๋Š” ์ฝ”์–ด ์ปดํฌ๋„ŒํŠธ ์ค‘์—๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์žˆ๋‹ค.

  • TextInput ์ปดํฌ๋„ŒํŠธ : focus(), blur()
  • ScrollView ์ปดํฌ๋„ŒํŠธ & FlatList ์ปดํฌ๋„ŒํŠธ : scrollToTop(), scrollToEnd()

์ปดํฌ๋„ŒํŠธ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๋ฉด ์ปดํฌ๋„ŒํŠธ์˜ ๋ฆฌ์•กํŠธ ์š”์†Œ (React Element, ๊ฐœ์ฒด ์ง€ํ–ฅ ์–ธ์–ด์—์„œ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์™€ ๊ฐ™์€ ๊ฐœ๋…) ์„ ์–ป์„ ์ˆ˜ ์žˆ์–ด์•ผ, ๊ฐœ์ฒด.๋ฉ”์†Œ๋“œ() ํ˜•ํƒœ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฆฌ์•กํŠธ์™€ ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋„๋ก ref ์†์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค. ์ปดํฌ๋„ŒํŠธ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ref.๋ฉ”์†Œ๋“œ() ํ˜•ํƒœ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿซง ๊ตฌํ˜„

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// T๋Š” FlatList, ScrollView, TextInput ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ
interface RefAttributes<T> extends Attributes
{ ref? : Ref<T> }
interface RefObject<T>
{ readonly current: T | null; }

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

// i.e.
const someRef = useRef<Some | null>(null)
<Some ref={someRef} />

someRef.current?.someMethod()
์ด ๊ธฐ์‚ฌ๋Š” ์ €์ž‘๊ถŒ์ž์˜ CC BY 4.0 ๋ผ์ด์„ผ์Šค๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.