λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
JavaScript/React-Native

[React-Native] React Native μ—μ„œ μ»΄ν¬λ„ŒνŠΈλž€

by soyλ―Έλ‹ˆ 2021. 11. 3.

 

 

 

 

 

πŸ’‘ μ»΄ν¬λ„ŒνŠΈλž€?

μž¬μ‚¬μš©ν•  수 μžˆλŠ” 쑰립 λΈ”λ‘μœΌλ‘œ, 화면에 λ‚˜νƒ€λ‚˜λŠ” UI μš”μ†Œμ΄λ‹€. κ·ΈλŸ¬λ‚˜ λ‹¨μˆœνžˆ UI μ—­ν• λ§Œ ν•˜λŠ” 것이 μ•„λ‹Œ λΆ€λͺ¨λ‘œλΆ€ν„° 받은 μ†μ„±μ΄λ‚˜ μžμ‹ μ˜ μƒνƒœμ— 따라 ν‘œν˜„μ΄ 달라지고 λ‹€μ–‘ν•œ κΈ°λŠ₯을 μˆ˜ν–‰ν•©λ‹ˆλ‹€. 

 

 

 

 

πŸ’‘ JSX

JSX λŠ” 마치 HTML 을 μž‘μ„±ν•œ 것 같은 μ½”λ“œμ΄λ‹€. μ΄λŸ¬ν•œ JSX λŠ” 객체 생성과 ν•¨μˆ˜ ν˜ΈμΆœμ„ μœ„ν•œ 문법적 편의λ₯Ό μ œκ³΅ν•˜κΈ° μœ„ν•΄ λ§Œλ“€μ–΄μ§„ ν™•μž₯ κΈ°λŠ₯으둜 λ¦¬μ•‘νŠΈ ν”„λ‘œμ νŠΈμ—μ„œ μ‚¬μš©λœλ‹€.

 

export default function App() {
  return (
    <View>
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

 

μ—¬λŸ¬ 개의 μš”μ†Œλ₯Ό ν‘œν˜„ν•  경우 ν•˜λ‚˜μ˜ λΆ€λͺ¨λ‘œ 감싸야 ν•œλ‹€. μœ„μ˜ 경우 Text 와 StatusBar νƒœκ·Έλ₯Ό View νƒœκ·Έλ‘œ 감싸고 μžˆλ‹€. View λŠ” UI λ₯Ό κ΅¬μ„±ν•˜λŠ” κ°€μž₯ 기본적인 μš”μ†Œλ‘œ μ›Ή ν”„λ‘œκ·Έλž˜λ°μ—μ„œ <div> 와 λΉ„μŠ·ν•œ 역할을 ν•˜λŠ” μ»΄ν¬λ„ŒνŠΈμ΄λ‹€. View μ»΄ν¬λ„ŒνŠΈμ²˜λŸΌ μ—¬λŸ¬ 개의 μ»΄ν¬λ„ŒνŠΈλ₯Ό λ°˜ν™˜ν•˜κ³  싢은 경우 Fragment μ»΄ν¬λ„ŒνŠΈλ₯Ό μ‚¬μš©ν•œλ‹€. Fragment νƒœκ·ΈλŠ” <Fragment> λ‘œλ„ μ‚¬μš©ν•˜κ³  단좕 λ¬Έλ²•μœΌλ‘œ <> λ‘œλ„ μ‚¬μš©ν•œλ‹€.

 

export default function App() {
  return (
    <>
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </>
  );
}

 

 

 

πŸ’‘ if λ¬Έ

JSX λ‚΄μ—μ„œ if 문을 μ‚¬μš©ν•˜λ €λ©΄ μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜ ν˜•νƒœλ‘œ μž‘μ„±ν•΄μ•Ό ν•œλ‹€.

 

export default function App() {
  const name = "hihi";
  return (
    <View style={styles.container}>
      <Text style={styles.text}>
        {(() => {
          if (name === "Hanbit") return "My name is Hanbit";
          else if (name === "Jeongmin") return "My name is Jeongmin";
          else return "My name is React Native";
        })()}
      </Text>
      <StatusBar style="auto" />
    </View>
  );
}

 

 

 

πŸ’‘ μ‚Όν•­ μ—°μ‚°μž

if 쑰건문 보닀 μ‚Όν•­ μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•  수 μžˆλ„λ‘ ν•˜κΈ°.

 

export default function App() {
  const name = "Jeongmin";
  return (
    <View style={styles.container}>
      <Text style={styles.text}>
        My name is {name === "Jeongmin" ? "Jeongmin Park" : "React Native"}
      </Text>
      <StatusBar style="auto" />
    </View>
  );
}

 

 

 

μ•± μ‹€ν–‰ ν™”λ©΄

 

 

 

 

 

 

πŸ’‘ AND / OR μ—°μ‚°μž

JSX μ—μ„œ false λŠ” λ Œλ”λ§λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— AND μ—°μ‚°μž μ•žμ˜ 쑰건이 참일 λ•Œ λ’€μ˜ λ‚΄μš©μ΄ λ‚˜νƒ€λ‚˜κ³  거짓인 경우 λ‚˜νƒ€λ‚˜μ§€ μ•ŠλŠ”λ‹€. OR μ—°μ‚°μžλŠ” AND μ—°μ‚°μžμ™€ λ°˜λŒ€λ‘œ μ•žμ˜ 쑰건이 거짓일 경우 λ‚΄μš©μ΄ λ‚˜νƒ€λ‚˜κ³  참일 경우 λ‚˜νƒ€λ‚˜μ§€ μ•ŠλŠ”λ‹€.

 

// AND μ—°μ‚°
export default function App() {
  const name = "Jeong";
  return (
    <View style={styles.container}>
      {name === "Jeongmin" && (
        <Text style={styles.text}>My name is Jeongmin</Text>
      )}
      {name !== "Jeongmin" && (
        <Text style={styles.text}>My name is not Jeongmin</Text>
      )}
      <StatusBar style="auto" />
    </View>
  );
}

 

// OR μ—°μ‚°
export default function App() {
  const name = "Jeongmin";
  return (
    <View style={styles.container}>
      {name !== "Jeongmin" || (
        <Text style={styles.text}>My name is Jeongmin</Text>
      )}
      {name === "Jeongmin" || (
        <Text style={styles.text}>My name is not Jeongmin</Text>
      )}
      <StatusBar style="auto" />
    </View>
  );
}

 

 

JSX μ—μ„œλŠ” null 은 ν—ˆμš©ν•˜μ§€λ§Œ undefined λŠ” ν—ˆμš©ν•˜μ§€ μ•ŠλŠ”λ‹€. (였λ₯˜ λ°œμƒ)

 

 

 

 

 

 

πŸ’‘ μŠ€νƒ€μΌλ§

JSX μ—μ„œλŠ” HTML κ³Ό 달리 style 에 λ¬Έμžμ—΄λ‘œ μž…λ ₯ν•˜λŠ” 것이 μ•„λ‹Œ 객체 ν˜•νƒœλ‘œ μž…λ ₯ν•΄μ•Ό ν•œλ‹€. 그리고 background-color 처럼 -(ν•˜μ΄ν”ˆ) 으둜 μ—°κ²°λœ 이름은 카멜 ν‘œκΈ°λ²•μœΌλ‘œ backgroundColor 처럼 μž‘μ„±ν•΄μ•Ό ν•œλ‹€.

 

export default function App() {
  const name = "Jeongmin";
  return (
    <View
      style={{
        flex: 1,
        backgroundColor: "#fff",
        alignItems: "center",
        justifyContent: "center",
      }}
    >
      {name !== "Jeongmin" || (
        <Text style={styles.text}>My name is Jeongmin</Text>
      )}
      {name === "Jeongmin" || (
        <Text style={styles.text}>My name is not Jeongmin</Text>
      )}
      <StatusBar style="auto" />
    </View>
  );
}

 

 

 

 

πŸ’‘ Button μ»΄ν¬λ„ŒνŠΈ

Button μ»΄ν¬λ„ŒνŠΈμ˜ onPress 및 title κ³Ό 같은 속성을 μ‚¬μš©ν•΄λ³΄μ•˜λ‹€.

 

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

const App = () => {
  return (
    <View
      style={{
        flex: 1,
        backgroundColor: "#fff",
        alignItems: "center",
        justifyContent: "center",
      }}
    >
      <Text style={{ fontSize: 30, marginBottom: 10 }}> Button Component</Text>
      <Button title="Button" onPress={() => alert("Click!!")} />
    </View>
  );
};

export default App;

 

 

 

 

μ•± μ‹€ν–‰ ν™”λ©΄

 

 

 

 

 

 

 

πŸ’‘ Custom μ»΄ν¬λ„ŒνŠΈ

Button μ»΄ν¬λ„ŒνŠΈλŠ” IOS 와 μ•ˆλ“œλ‘œμ΄λ“œμ—μ„œ λ‹€λ₯Έ λͺ¨μŠ΅μœΌλ‘œ λ Œλ”λ§ 되기 λ•Œλ¬Έμ— κ·Έ 점을 λ³΄μ™„ν•˜κΈ° μœ„ν•΄μ„œ TouchableOpacity μ»΄ν¬λ„ŒνŠΈμ™€ Text μ»΄ν¬λ„ŒνŠΈλ₯Ό μ΄μš©ν•΄μ„œ MyButton μ»€μŠ€ν…€ μ»΄ν¬λ„ŒνŠΈλ₯Ό λ§Œλ“€μ—ˆλ‹€.

 

// src/components/MyButton.js
import React from "react";
import { TouchableOpacity, Text } from "react-native";

const MyButton = () => {
  return (
    <TouchableOpacity
      style={{
        backgroundColor: "#3498db",
        padding: 16,
        margin: 10,
        borderRadius: 8,
      }}
      onPress={() => alert("Click!!")}
    >
      <Text
        style={{
          fontSize: 24,
          color: "white",
        }}
      >
        My Button
      </Text>
    </TouchableOpacity>
  );
};

export default MyButton;

 

// src/App.js
import React from "react";
import { Text, Button, View } from "react-native";
import MyButton from "./components/MyButton";

const App = () => {
  return (
    <View
      style={{
        flex: 1,
        backgroundColor: "#fff",
        alignItems: "center",
        justifyContent: "center",
      }}
    >
      <Text style={{ fontSize: 30, marginBottom: 10 }}> My Button Component</Text>
      <MyButton/>
    </View>
  );
};

export default App;

 

 

 

 

μ•± μ‹€ν–‰ ν™”λ©΄

 

 

 

 

 

 

 

πŸ’‘ props

props λž€, λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈλ‘œλΆ€ν„° μ „λ‹¬λœ 속성값 ν˜Ήμ€ 상속받은 μ†μ„±κ°’μœΌλ‘œ λ³€κ²½ν•  수 μ—†λ‹€.

 

// src/components/MyButton.js
import React from "react";
import { TouchableOpacity, Text } from "react-native";

const MyButton = (props) => {
  return (
    <TouchableOpacity
      style={{
        backgroundColor: "#3498db",
        padding: 16,
        margin: 10,
        borderRadius: 8,
      }}
      onPress={() => alert("Click!!")}
    >
      <Text
        style={{
          fontSize: 24,
          color: "white",
        }}
      >
        {/* children 이 μžˆλ‹€λ©΄ title 보닀 더 μš°μ„ μ‹œλ˜λ„λ‘ ν•˜λŠ” 것 */}
        {props.children || props.title}
      </Text>
    </TouchableOpacity>
  );
};

MyButton.defaultProps = {
  title: "Default",
};

export default MyButton;

 

props.children 은 App.js μ—μ„œ μ„ μ–Έν•œ MyButton μ»΄ν¬λ„ŒνŠΈ μ‚¬μ΄μ˜ κ°’ "Children Props" 이닀.

props.title 은 App.js μ—μ„œ μ„ μ–Έν•œ MyButton μ»΄ν¬λ„ŒνŠΈ μ•ˆμ— μ „λ‹¬ν•œ props 인 title 의 κ°’ "Button" 이닀.

 

// src/App.js
import React from "react";
import { Text, Button, View } from "react-native";
import MyButton from "./components/MyButton";

const App = () => {
  return (
    <View
      style={{
        flex: 1,
        backgroundColor: "#fff",
        alignItems: "center",
        justifyContent: "center",
      }}
    >
      <Text style={{ fontSize: 30, marginBottom: 10 }}>Props</Text>
      <MyButton title="Button" />
      <MyButton title="Button">Children Props</MyButton>
      {/* title 에 μ „λ‹¬λœ 값이 없을 경우 Default κ°€ title κ°’μœΌλ‘œ λ“€μ–΄μ˜¨λ‹€. */}
      <MyButton />
    </View>
  );
};

export default App;

 

 

 

μ•± μ‹€ν–‰ ν™”λ©΄

 

 

 

 

 

πŸ’‘ PropTypes

λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—μ„œ 전달받아야 ν•˜λŠ” props 의 νƒ€μž…κ³Ό ν•„μˆ˜ μ—¬λΆ€λ₯Ό 지정할 수 μžˆλ‹€.

npm install prop-types

 

// src/components/MyButton.js

import React from "react";
import { TouchableOpacity, Text } from "react-native";
import PropTypes from "prop-types";

const MyButton = (props) => {
  return (
    <TouchableOpacity
      style={{
        backgroundColor: "#3498db",
        padding: 16,
        margin: 10,
        borderRadius: 8,
      }}
        {/* λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ „λ‹¬ν•œ onPress ν•¨μˆ˜λ₯Ό 이벀트둜 λ°›λŠ”λ‹€. */}
      onPress={() => props.onPress()}
    >
      <Text
        style={{
          fontSize: 24,
          color: "white",
        }}
      >
        {/* children 값이 μžˆλ‹€λ©΄ title 이 μžˆμ–΄λ„ children 값을 보이도둝 ν•˜λŠ” 것 */}
        {props.children || props.title}
      </Text>
    </TouchableOpacity>
  );
};

MyButton.propTypes = {
  title: PropTypes.string.isRequired,
  onPress: PropTypes.func.isRequired,
};

MyButton.defaultProps = {
  title: "Default",
};

export default MyButton;

 

λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈ (App.js) μ—μ„œ μ „λ‹¬ν•œ props μ—μ„œ onPress λ₯Ό κΊΌλ‚΄μ„œ λ²„νŠΌ 이벀트둜 μž…λ ₯ν•œλ‹€.

 

 

// src/App.js

import React from "react";
import { Text, Button, View } from "react-native";
import MyButton from "./components/MyButton";

const App = () => {
  return (
    <View
      style={{
        flex: 1,
        backgroundColor: "#fff",
        alignItems: "center",
        justifyContent: "center",
      }}
    >
      <Text style={{ fontSize: 30, marginBottom: 10 }}>Props</Text>
      <MyButton title="Button" onPress={() => alert("props")} />
      <MyButton title="Button" onPress={() => alert("children")}>
        Children Props
      </MyButton>
      {/* title 에 μ „λ‹¬λœ 값이 없을 경우 Default κ°€ title κ°’μœΌλ‘œ λ“€μ–΄μ˜¨λ‹€. */}
      <MyButton onPress={() => alert("default")} />
    </View>
  );
};

export default App;

 

 

 

 

 

πŸ’‘ state

state λž€, μ»΄ν¬λ„ŒνŠΈμ—μ„œ μƒμ„±λ˜κ³  변경이 κ°€λŠ₯ν•œ 값이며 state λ₯Ό μ΄μš©ν•΄μ„œ μ»΄ν¬λ„ŒνŠΈ μƒνƒœλ₯Ό κ΄€λ¦¬ν•œλ‹€. Hook 을 μ΄μš©ν•΄μ„œ ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈμ—μ„œλ„ μƒνƒœ 관리가 κ°€λŠ₯ν•˜λ‹€.

 

// src/components/Counter.js

import React, { useState } from "react";
import { View, Text } from "react-native";
import MyButton from "./MyButton";

const Counter = () => {
  const [count, setCount] = useState(0);
  return (
    <>
      <View style={{ alignItems: "center" }}>
        <Text style={{ fontSize: 30, margin: 10 }}>{count}</Text>
        <MyButton onPress={() => setCount(count + 1)}>증가</MyButton>
        <MyButton onPress={() => setCount(count - 1)}>κ°μ†Œ</MyButton>
      </View>
    </>
  );
};
export default Counter;

 

count 에 λŒ€ν•œ μƒνƒœκ΄€λ¦¬λ₯Ό μœ„ν•΄ useState(0) λ₯Ό μ‚¬μš©ν–ˆλ‹€.

μ¦κ°€ν•˜λŠ” λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄ setCount κ°€ +1 이 되고 κ°μ†Œν•˜λŠ” λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄ setCount κ°€ -1 이 λœλ‹€.

 

 

// src/App.js

import React from "react";
import { Text, Button, View } from "react-native";
import MyButton from "./components/MyButton";
import Counter from "./components/Counter";

const App = () => {
  return (
    <View
      style={{
        flex: 1,
        backgroundColor: "#fff",
        alignItems: "center",
        justifyContent: "center",
      }}
    >
      <Text style={{ fontSize: 30, marginBottom: 10 }}>Props</Text>
      <Counter />
    </View>
  );
};

export default App;

 

 

 

μ•± μ‹€ν–‰ ν™”λ©΄

 

 

 

 

 

 

 

πŸ’‘ useState μ—¬λŸ¬ 개 μ‚¬μš©ν•˜κΈ°

 

import React, { useState } from "react";
import { View, Text } from "react-native";
import MyButton from "./MyButton";

const Counter = () => {
  const [count, setCount] = useState(0);
  const [double, setDouble] = useState(0);

  return (
    <>
      <View style={{ alignItems: "center" }}>
        <Text style={{ fontSize: 30, margin: 10 }}>count : {count+double}</Text>
        <MyButton onPress={() => setCount(count + 1)}>증가</MyButton>
        <MyButton onPress={() => setCount(count - 1)}>κ°μ†Œ</MyButton>
        <MyButton onPress={() => setDouble(double + 2)}>2 증가</MyButton>
        <MyButton onPress={() => setDouble(double - 2)}>2 κ°μ†Œ</MyButton>
      </View>
    </>
  );
};
export default Counter;

 

 

 

 

μ•± μ‹€ν–‰ ν™”λ©΄

 

 

 

 

 

 

 

πŸ’‘ Press Event

μ‚¬μš©μžκ°€ νŠΉμ • DOM 을 ν΄λ¦­ν–ˆμ„ λ•Œ ν˜ΈμΆœλ˜λŠ” onClick μ΄λ²€νŠΈμ™€ λΉ„μŠ·ν•œ μ΄λ²€νŠΈκ°€ press μ΄λ²€νŠΈμ΄λ‹€. TouchableOpacity μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ„€μ •ν•  수 μžˆλŠ” Press 이벀트의 μ’…λ₯˜λŠ” 총 4 가지이닀. 

 

1. onPressIn : ν„°μΉ˜κ°€ μ‹œμž‘λ  λ•Œ 호좜

2. onPressOut : ν„°μΉ˜κ°€ ν•΄μ œλ  λ•Œ 호좜

3. onPress : ν„°μΉ˜κ°€ ν•΄μ œλ  λ•Œ onPressOut 이후 호좜

4. onLongPress : ν„°μΉ˜κ°€ 일정 μ‹œκ°„ 이상 μ§€μ†λ˜λ©΄ 호좜

 

// src/components/EventButton.js

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

const EventButton = () => {
  const _onPressIn = () => console.log("Press In !!!\n");
  const _onPressOut = () => console.log("Press Out !!!\n");
  const _onPress = () => console.log("Press !!!\n");
  const _onLongPress = () => console.log("Long Press !!!\n");
  return (
    <TouchableOpacity
      style={{
        backgroundColor: "#f1c40f",
        padding: 16,
        margin: 10,
        borderRadius: 8,
      }}
      onPressIn={_onPressIn}
      onLongPress={_onLongPress}
      onPressOut={_onPressOut}
      onPress={_onPress}
      delayLongPress={3000}
    >
      <Text style={{ color: "white", fontSize: 24 }}>Press</Text>
    </TouchableOpacity>
  );
};
export default EventButton;

 

λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄

- 짧게 클릭할 경우 : Press In -> Press Out -> Press

- 길게 클릭할 경우 : Press In -> Long Press -> Press Out

 

 

delayLongPress={3000} 은 3초 λ™μ•ˆ λ²„νŠΌμ„ λˆ„λ₯΄κ³  μžˆμ–΄μ•Ό onLongPress κ°€ ν˜ΈμΆœλœλ‹€λŠ” μ˜λ―Έμ΄λ‹€.

 

 

 

 

μ•± μ‹€ν–‰ ν™”λ©΄

 

 

 

 

 

 

 

πŸ’‘ onChange Event

 

// src/components/EventInput.js

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

const EventInput = () => {
  const [text, setText] = useState("");
  const _onChange = (event) => setText(event.nativeEvent.text);
  const _onChangeText = (text) => {
    setText(text);
    console.log("text: ", text);
  };

  return (
    <>
      <View>
        <Text style={{ margin: 10, fontSize: 30 }}>text: {text}</Text>
        <TextInput
          style={{ borderWidth: 1, padding: 10, fontSize: 20 }}
          placeholder="Enter a text...."
          //   onChange={_onChange}
          onChangeText={_onChangeText}
        />
      </View>
    </>
  );
};

export default EventInput;

 

onChange λŠ” μ‹€μ‹œκ°„μœΌλ‘œ λ³€ν™”ν•˜λŠ” ν…μŠ€νŠΈμ΄κ³ , μ‹€μ œλ‘œ ν•„μš”ν•œ λ°μ΄ν„°λŠ” onChangeText 이닀. 즉, μ»΄ν¬λ„ŒνŠΈμ˜ ν…μŠ€νŠΈκ°€ λ³€κ²½λ˜μ—ˆμ„ λ•Œ λ³€κ²½λœ ν…μŠ€νŠΈμ˜ λ¬Έμžμ—΄λ§Œ 인수둜 μ „λ‹¬ν•˜λ©° ν˜ΈμΆœν•˜λŠ” 것이닀.

 

 

 

 

 

μ•± μ‹€ν–‰ ν™”λ©΄

 

 

 

 

 

 

 

 

 

λ³Έ ν¬μŠ€νŒ…μ€ λ„μ„œ [처음 λ°°μš°λŠ” λ¦¬μ•‘νŠΈ λ„€μ΄ν‹°λΈŒ(ν•œλΉ›λ―Έλ””μ–΄, κΉ€λ²”μ€€ μ§€μŒ)] λ₯Ό 보고 κ³΅λΆ€ν•˜λ©° κΈ°λ‘ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

'JavaScript > React-Native' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[React-Native] μ»΄ν¬λ„ŒνŠΈ μŠ€νƒ€μΌλ§  (0) 2021.11.04
[React-Native] React Native μ‹œμž‘ν•˜κΈ°  (0) 2021.11.02

λŒ“κΈ€