Gihak111 Navbar

콘텍스트와 ref 속성

리액티브 네이티브에서 중요한 역할을 한다.

1. 콘텍스트

콘텍스트

콘텍스트는 리액트 애플리케이션에서 컴포넌트 트리 전체에 데이터를 전달하는 방법이다.
깊이 중첩된 컴포넌트에 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 훅을 통해 테마 상태와 테마 변경 함수를 쉽게 사용할 수 있다.

이 기능을 사용하면 모든 컴포넌트가 현재 테마에 접근하고, 테마를 변경할 수 있다.

2. useRef 훅과 ref 속성

useRef 훅과 ref 속성

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;

3. useImperativeHandle 훅

useImperativeHandle

useImperativeHandle 훅은 부모 컴포넌트가 자식 컴포넌트의 인스턴스 값을 변경할 수 있게 한다.
이를 통해 자식 컴포넌트의 내부 메서드를 외부에 노출할 수 있다.

역할과 사용 이유

CustomInput 의 역할

이 기능을 사용하면 부모 컴포넌트가 자식 컴포넌트의 내부 메서드를 쉽게 제어할 수 있다.

useImperativeHandle 훅

부모 컴포넌트가 자식 컴포넌트의 인스턴스 값을 변경할 수 있게한다.
이를 통해 자식 컴포넌트의 내부 메서드를 노출할 수 있다.

다음은 테마 컴포넌트 구현 및 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 메서드를 정의하고, 부모 컴포넌트에서 이를 호출할 수 있다.

정리

이 모든 기능은 리액트 네이티브 애플리케이션에서 컴포넌트 간의 데이터 공유와 상호 작용을 더욱 간단하고 효율적으로 만든다. 각 기능을 언제 어떻게 사용하는지 이해하고 나면, 더 복잡한 애플리케이션을 쉽게 개발할 수 있다.