본문 바로가기
Frontend/React Native

React Native 1-2. 코어컴포넌트, prop, React Hooks

by 디스코비스킷 2025. 3. 6.
반응형

Ch 03. React Native 학습 시 주요 개념

1. Core Components

Android와 iOS의 UI 컴포넌트 구조 차이가 있지만

React Native는 같은 JSX 코드를 사용해도 Android와 iOS에서 각각 네이티브 UI 컴포넌트로 변환됨.

  • Android에서는 내부적으로 ViewGroup > ImageView + TextView 로 변환.
  • iOS에서는 내부적으로 UIView > UIImageView + UITextView 로 변환.

한 번의 코드 작성으로 Android & iOS 모두 대응 가능!

React Native의 코어 컴포넌트(Core Components)란?

React Native에서 기본적으로 제공되는 UI 요소를 의미한다.
React에서

, , 같은 웹 요소를 사용하듯이,
React Native에서는 모바일 앱에 맞는 네이티브 컴포넌트를 제공한다.

주요 코어 컴포넌트 정리

컴포넌트 설명 비고
View div와 비슷한 컨테이너 역할 레이아웃 잡을 때 필수
Text 텍스트를 렌더링하는 컴포넌트 div 안에처럼 써야 함
Image 이미지를 표시하는 컴포넌트 source={{ uri: "url" }} 형태
ScrollView 스크롤 가능한 화면 flex: 1 설정 자주 필요
FlatList 성능 최적화된 리스트 렌더링 대량 데이터 표시 시 사용
TouchableOpacity 터치 가능한 버튼 역할 터치 시 투명도 조절 효과
TextInput 사용자가 입력할 수 있는 필드 onChangeText로 값 업데이트
Button 기본 버튼 제공 커스터마이징 어려움
SafeAreaView 노치 있는 디바이스에서 안전한 영역 iPhoneX 이후 필수

button은 다르게 만들어서 쓴다.

추후 설명..

2. 컴포넌트와 prop

1. 컴포넌트(Component)란?

재사용 가능한 개별적인 UI 조각

  • React Native에서 UI를 구성하는 기본 단위
  • 여러 개의 컴포넌트를 조합하여 화면을 구성
  • 유지보수와 재사용성을 높일 수 있음

2. Prop(속성)이란?

부모 → 자식 컴포넌트로 데이터를 전달하는 방법

  • 부모 컴포넌트에서 자식 컴포넌트로 값을 내려주는 역할
  • 자식 컴포넌트에서는 부모로부터 받은 prop을 직접 수정할 수 없음(불변성)

props.name은 부모에서 넘겨준 값이라 자식에서 변경 불가!
만약 변경하고 싶다면 부모에서 상태(state)로 관리해야 함

3. 컴포넌트의 종류

1) 클래스형 컴포넌트 (Class Component)

  • 예전 방식, 현재는 거의 사용 안 함
  • state와 생명주기 메서드(componentDidMount 등)을 가짐
  • React Native에서 React.Component를 상속받아 사용
  • class 키워드 필요
  • render() 메서드 반드시 필요
  • 함수형보다 메모리 자원을 더 사용한다
import React, { Component } from "react";
import { Text, View } from "react-native";

class MyClassComponent extends Component {
  render() {
    return (
      <View>
        <Text>Hello, {this.props.name}!</Text>
      </View>
    );
  }
}

2) 함수형 컴포넌트 (Function Component)

  • 현재 React Native에서 주로 사용되는 방식!
  • state, lifeCycle관련 기능 사용 불가능 useState, useEffect 같은 훅(Hook)과 함께 사용 가능
const MyFunctionComponent = ({ name }) => {
  return (
    <View>
      <Text>Hello, {name}!</Text>
    </View>
  );
};

📌 현재는 함수형 컴포넌트 + 훅(Hooks) 조합이 표준!

3. 컴포넌트와 prop : 실습

카카오톡창(친구목록)을 보고 대충 컴포넌트를 익히기위한 실습이었다.

코드보기 👇🏻👇🏻👇

import React from 'react';
import { Image, StyleSheet, Text, View } from "react-native";

const Header = (props: any) => <Text>{props.title}</Text>;
const MyProfile = () => (
  <Text>
    <Profile
      uri="https://i.namu.wiki/i/pKp6bM6ovVkqzTlwj5lkWjCfyLCITAU3bP5chwJc7TcsgEh9dJxNGbAUfnTTlFsjAzmIG586bMk56Oa5OgHEZw.webp"
      name="카리나"
      profileSize={64}
    />
  </Text>
);
const Profile = (props: any) => {
  return (
    <View style={{ flexDirection: "row" }}>
      <Image
        source={{
          uri: props.uri
        }}
        style={{
          width: props.profileSize,
          height: props.profileSize,
        }}
      />
      <Text>{props.name}</Text>
    </View>
  );
}
const Division = () => <Text>Division</Text>;
const FriendSection = () => (
  <Text></Text>
);
const FriendList = () => {
  return (
    <View>
      <Profile
        uri="https://i.namu.wiki/i/pKp6bM6ovVkqzTlwj5lkWjCfyLCITAU3bP5chwJc7TcsgEh9dJxNGbAUfnTTlFsjAzmIG586bMk56Oa5OgHEZw.webp"
        name="카리나"
        profileSize={50}
      />
      <Profile
        uri="https://i.namu.wiki/i/pKp6bM6ovVkqzTlwj5lkWjCfyLCITAU3bP5chwJc7TcsgEh9dJxNGbAUfnTTlFsjAzmIG586bMk56Oa5OgHEZw.webp"
        name="카리나"
        profileSize={50}
      />
      <Profile
        uri="https://i.namu.wiki/i/pKp6bM6ovVkqzTlwj5lkWjCfyLCITAU3bP5chwJc7TcsgEh9dJxNGbAUfnTTlFsjAzmIG586bMk56Oa5OgHEZw.webp"
        name="카리나"
        profileSize={50}
      />
      <Profile
        uri="https://i.namu.wiki/i/pKp6bM6ovVkqzTlwj5lkWjCfyLCITAU3bP5chwJc7TcsgEh9dJxNGbAUfnTTlFsjAzmIG586bMk56Oa5OgHEZw.webp"
        name="카리나"
        profileSize={50}
      />
    </View>
  );
}


export default function HomeScreen() {
  return (
    <View>
      <Header title="친구"/>
      <MyProfile />
      <Division />
      <FriendSection />
      <FriendList />
    </View>
  );
}

const styles = StyleSheet.create({
  titleContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
  },
  stepContainer: {
    gap: 8,
    marginBottom: 8,
  },
  reactLogo: {
    height: 178,
    width: 290,
    bottom: 0,
    left: 0,
    position: 'absolute',
  },
});

ios 시뮬레이터 써보고싶어서 설정하느라 시간 다 갔음

https://disco-biscuit.tistory.com/151
리액트 좀 써봐서 비슷한데 다른부분이 많다.

 

TML요소랑 코어컴포넌트가 대응되는게 있어서 정리해봤다.

컴포넌트 설명 비고
View div와 비슷한 컨테이너 역할 레이아웃 잡을 때 필수
Text 텍스트를 렌더링하는 컴포넌트 div 안에 <p>처럼 써야 함
Image 이미지를 표시하는 컴포넌트 source={{ uri: "url" }} 형태
ScrollView 스크롤 가능한 화면 flex: 1 설정 자주 필요
FlatList 성능 최적화된 리스트 렌더링 대량 데이터 표시 시 사용
TouchableOpacity 터치 가능한 버튼 역할 터치 시 투명도 조절 효과
TextInput 사용자가 입력할 수 있는 필드 onChangeText로 값 업데이트
Button 기본 버튼 제공 커스터마이징 어려움
SafeAreaView 노치 있는 디바이스에서 안전한 영역 iPhoneX 이후 필수

 

4. React Hooks (1) useState 이론&실습

클래스형컴포넌트에서 state

  import React from "react";
import { Button, Text, View } from "react-native";

class Component extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }

  render() {
    return (
      <View>
        <Text>You clicked {this.state.count} times</Text>
        <Button
          title="Click me"
          onPress={() => this.setState({ count: this.state.count + 1 })}
        />
      </View>
    );
  }
}

export default Component;

함수형컴포넌트에서 state(useState)

  import React, { useState } from "react";
import { Button, Text, View } from "react-native";

const Component = () => {
  const [count, setCount] = useState(0);

  return (
    <View>
      <Text>You clicked {count} times</Text>
      <Button title="Click me" onPress={() => setCount(count + 1)} />
    </View>
  );
};

export default Component;

클래스형컴포넌트보다 함수형 컴포넌트로 쓰는것이 더 짧고 가독성이 좋음.

5. React Hooks (2) useEffect 이론_실습

 

// didmount
useEffect(() => {...}, [])

// didupate
useEffect(() => {...}, [state])

// willunmount
useEffect(() => {
  return () => {
    // 언마운트될때 실행될 코드
  };
}, []); 

useEffect로 didMount와 didUpdate, willUnmount를 대체할수있음

 

6. React Hooks (3) custom 이론_실습

인풋에서 값을 받아 state에 저장하고 초기화할수있는 컴포넌트이다. 

똑같은게 3개라서 코드중복이 있다. 

 

customHook.js

import React, { useState } from "react";
import { Button, StyleSheet, TextInput, View } from "react-native";

const InputBox = (props) => {
  return (
    <View style={styles.flex}>
      <TextInput
        value={props.value}
        onChangeText={props.onChangeText}
        placeholder={props.placeholder}
        style={styles.input}
      />
      <Button title="초기화" onPress={props.onReset} />
    </View>
  );
};

const CustomHook = () => {
  const [name, setName] = useState("");
  const [age, setAge] = useState(0);
  const [city, setCity] = useState("");

  return (
    <View style={styles.container}>
      <InputBox
        value={name}
        onChangeText={setName}
        placeholder="이름을 입력하세요"
        onReset={() => setName("")}
      />
      <InputBox
        value={age}
        onChangeText={setAge}
        placeholder="나이를 입력하세요"
        onReset={() => setAge("")}
      />
      <InputBox
        value={city}
        onChangeText={setCity}
        placeholder="도시을 입력하세요"
        onReset={() => setCity("")}
      />
    </View>
  );
};
export default CustomHook;

UI부분에서 InputBox로 반복되는 컴포넌트를 따로 빼서 재사용가능한 컴포넌트로 빼주었지만
onChangeText나 onReset등 코드가 여전히 반복됨  -> 커스텀훅이 필요하다.

// custom hook
const useInput = (initialValue) => {
  const [value, setValue] = useState(initialValue);
  const resetValue = () => setValue(initialValue);

  return {
    value,
    setValue,
    resetValue,
  };
};

커스텀훅 안에서 useState로 생성할거임

useState부분을 커스텀훅사용하기위해 변경하기

 

const CustomHook = () => {
  // const [name, setName] = useState("");
  const output = useInput("");
  const name = output.value;
  const setName = output.setValue;
  const resetName = output.resetValue;
  ...

이렇게 작성하면 길기때문에

 

const CustomHook = () => {
    // refactored    구조분해할당
  const {
    value: name,
    setValue: setName,
    resetValue: resetName,
  } = useInput("");

한줄로 커스텀훅 사용

 

그리고 onReset에서
onReset={() => setCity("")}onReset={resetCity}로 사용하여
명시적인 초기화 함수를 전달한다.

 

 

커스텀훅사용 최종코드

import React, { useState } from "react";
import { Button, StyleSheet, TextInput, View } from "react-native";

const InputBox = (props) => {
  return (
    <View style={styles.flex}>
      <TextInput
        value={props.value}
        onChangeText={props.onChangeText}
        placeholder={props.placeholder}
        style={styles.input}
      />
      <Button title="초기화" onPress={props.onReset} />
    </View>
  );
};

// custom hook
const useInput = (initialValue) => {
  const [value, setValue] = useState(initialValue);
  const resetValue = () => setValue(initialValue);

  return {
    value,
    setValue,
    resetValue,
  };
};

const CustomHook = () => {
  const {
    value: name,
    setValue: setName,
    resetValue: resetName,
  } = useInput("");
  const {
    value: city,
    setValue: setCity,
    resetValue: resetCity,
  } = useInput("");
  const {
    value: age,
    setValue: setAge,
    resetValue: resetAge,
  } = useInput("");

  // const [age, setAge] = useState(0);
  // const [city, setCity] = useState("");

  return (
    <View style={styles.container}>
      <InputBox
        value={name}
        onChangeText={setName}
        placeholder="이름을 입력하세요"
        onReset={resetName}
      />
      <InputBox
        value={age}
        onChangeText={setAge}
        placeholder="나이를 입력하세요"
        onReset={resetAge}
      />
      <InputBox
        value={city}
        onChangeText={setCity}
        placeholder="도시을 입력하세요"
        onReset={resetCity}
      />
    </View>
  );
};

export default CustomHook;
반응형

최근댓글

최근글

© Copyright 2024 ttutta