리액티브 네이티브에서 중요한 역할을 한다.
콘텍스트는 리액트 애플리케이션에서 컴포넌트 트리 전체에 데이터를 전달하는 방법이다.
깊이 중첩된 컴포넌트에 props를 일일이 전달하지 않고도 데이터를 공유할 수 있다.
주로 ‘테마’, ‘사용자 정보’, ‘설정’과 같은 글로벌 데이터를 관리하는 데 사용된다.
예제를 통해 알아보자.
전체적인 스타일을 정의하고, 이를 텀포넌트 전체에서 일관되게 사용할 수 있도록 한다.
Provider 컴포넌트와 useTheme 커스텀 훅 구현
// ThemeContext.js
import React, { createContext, useState, useContext } from 'react';
// 1. 테마 컨텍스트 생성
const ThemeContext = createContext();
// 2. 테마 제공자 컴포넌트 정의
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light'); // 기본 테마는 'light'
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
};
return (
<ThemeContext.Provider value=>
{children}
</ThemeContext.Provider>
);
};
// 3. 테마를 사용하는 커스텀 훅 정의
export const useTheme = () => useContext(ThemeContext);
// App.js
import React from 'react';
import { ThemeProvider, useTheme } from './ThemeContext';
import { View, Text, Button, StyleSheet } from 'react-native';
// 테마에 따라 스타일을 변경하는 컴포넌트
const ThemedComponent = () => {
const { theme, toggleTheme } = useTheme();
const styles = getStyles(theme);
return (
<View style={styles.container}>
<Text style={styles.text}>Current Theme: {theme}</Text>
<Button title="Toggle Theme" onPress={toggleTheme} />
</View>
);
};
const App = () => {
return (
<ThemeProvider>
<ThemedComponent />
</ThemeProvider>
);
};
// 테마에 따라 다른 스타일을 반환하는 함수
const getStyles = (theme) =>
StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: theme === 'light' ? '#fff' : '#333',
},
text: {
color: theme === 'light' ? '#000' : '#fff',
},
});
export default App;
ThemeProvider를 통해 테마 상태를 제공하고, useTheme 훅을 통해 테마 상태와 테마 변경 함수를 쉽게 사용할 수 있다.
이 기능을 사용하면 모든 컴포넌트가 현재 테마에 접근하고, 테마를 변경할 수 있다.
useRef 훅
DOM 요소나 클래스 인스턴스와 같은 변경되지 않는 값을 유지하는 데 사용한다.
함수형 컴포넌트에서 변경 가능한 ref 객체를 생성한다.
주로 DOM 요소나 클래스 인스턴스를 참조할 때 , 포커스, 텍스트 선택, 미디어 재생 등 직접적으로 DOM 요소를 조작할 때 유용하다.
ref 속성 특정 DOM 요소나 컴포넌트 인스턴스를 참조하는데 사용된다.
useRef 훅과 이를 활용한 input.tsx 파일 구현
// InputComponent.tsx
import React, { useRef } from 'react';
import { TextInput, View, Button } from 'react-native';
const InputComponent = () => {
const inputRef = useRef(null); // 1. useRef 훅으로 참조 객체 생성
const focusInput = () => {
if (inputRef.current) {
inputRef.current.focus(); // 2. input 요소에 포커스를 맞추는 함수
}
};
return (
<View>
<TextInput ref={inputRef} style= />
<Button title="Focus the input" onPress={focusInput} />
</View>
);
};
export default InputComponent;
// TestInput.tsx
import React from 'react';
import { ScrollView, View } from 'react-native';
import InputComponent from './InputComponent';
const TestInput = () => {
return (
<ScrollView>
<View style=>
<InputComponent />
</View>
</ScrollView>
);
};
export default TestInput;
커스텀 훅도 만들어 보자.
// AutoFocusProvider.js
import React, { createContext, useRef, useEffect, useContext } from 'react';
// 1. AutoFocus 컨텍스트 생성
const AutoFocusContext = createContext(null);
export const AutoFocusProvider = ({ children }) => {
const inputRef = useRef(null);
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus(); // 2. 컴포넌트가 마운트되면 자동으로 포커스 맞추기
}
}, []);
return (
<AutoFocusContext.Provider value={inputRef}>
{children}
</AutoFocusContext.Provider>
);
};
export const useAutoFocus = () => useContext(AutoFocusContext);
// AutoFocusInput.js
import React from 'react';
import { TextInput } from 'react-native';
import { useAutoFocus } from './AutoFocusProvider';
const AutoFocusInput = () => {
const inputRef = useAutoFocus(); // 3. 자동 포커스 훅 사용
return <TextInput ref={inputRef} style= />;
};
export default AutoFocusInput;
// App.js
import React from 'react';
import { View } from 'react-native';
import { AutoFocusProvider } from './AutoFocusProvider';
import AutoFocusInput from './AutoFocusInput';
const App = () => {
return (
<AutoFocusProvider>
<View style=>
<AutoFocusInput />
</View>
</AutoFocusProvider>
);
};
export default App;
useImperativeHandle
훅은 부모 컴포넌트가 자식 컴포넌트의 인스턴스 값을 변경할 수 있게 한다.
이를 통해 자식 컴포넌트의 내부 메서드를 외부에 노출할 수 있다.
focus
와 clear
메서드를 외부에 노출한다.CustomInput
의 focus
와 clear
메서드를 버튼 클릭 시 호출한다.이 기능을 사용하면 부모 컴포넌트가 자식 컴포넌트의 내부 메서드를 쉽게 제어할 수 있다.
부모 컴포넌트가 자식 컴포넌트의 인스턴스 값을 변경할 수 있게한다.
이를 통해 자식 컴포넌트의 내부 메서드를 노출할 수 있다.
다음은 테마 컴포넌트 구현 및 forwardRef API 사용 예제이다.
// CustomInput.js
import React, { useRef, forwardRef, useImperativeHandle } from 'react';
import { TextInput, View, Button } from 'react-native';
// 1. forwardRef를 사용하여 ref 전달
const CustomInput = forwardRef((props, ref) => {
const inputRef = useRef(null);
// 2. useImperativeHandle을 사용하여 외부에 노출할 메서드 정의
useImperativeHandle(ref, () => ({
focus: () => {
if (inputRef.current) {
inputRef.current.focus();
}
},
clear: () => {
if (inputRef.current) {
inputRef.current.clear();
}
},
}));
return <TextInput ref={inputRef} style= />;
});
export default CustomInput;
// App.js
import React, { useRef } from 'react';
import { View, Button } from 'react-native';
import CustomInput from './CustomInput';
const App = () => {
const customInputRef = useRef(null);
return (
<View style=>
<CustomInput ref={customInputRef} />
<Button title="Focus the input" onPress={() => customInputRef.current.focus()} />
<Button title="Clear the input" onPress={() => customInputRef.current.clear()} />
</View>
);
};
export default App;
CustomInput 컴포넌트에서 focus와 clear 메서드를 정의하고, 부모 컴포넌트에서 이를 호출할 수 있다.
이 모든 기능은 리액트 네이티브 애플리케이션에서 컴포넌트 간의 데이터 공유와 상호 작용을 더욱 간단하고 효율적으로 만든다. 각 기능을 언제 어떻게 사용하는지 이해하고 나면, 더 복잡한 애플리케이션을 쉽게 개발할 수 있다.