[스파르타코딩클럽 앱개발 3주차] 정리용

노치현·2022년 9월 4일
0

스파르타코딩클럽 앱개발종합반 3주차를 요약하자면,
React Native의 구조와 Stack Navigator라 할 수 있다.

React Native의 구조

리액트 네이티브는 리액트(React.js) 라이브러리 기반으로 만들어진 프레임워크이기에 기본적인 구조는 리액트와 유사하다.

component, props, useEffect, useState를 잘 이해할 필요가 있다.

component: 한 화면을 구성하는 요소(엘리먼트)로, 한 화면 전체가 컴포넌트가 될 수 있다. 버튼이 될 수도, 하나의 js파일로 구성된 화면이 될 수도 있는 것

function Exercise(props) {
		return <h1>Hello</h1>;
	}

props로 받을 객체 인자를 정의하고, return 문으로 JSX를 반환하는 것으로 기본 형태를 갖춘다.

주로 함수로 정의되어 재활용이 용이한게 특징으로, 자주쓰는 컴포넌트들을 폴더(디렉토리)에 보관해놓고 경로에 해당하는 컴포넌트를 적재적소에 꺼내쓸 수 있음.

Card. js

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

//비구조 할당 방식으로 넘긴 속성 데이터를 꺼내 사용함
export default function Card({content}) {
    return (<View style={styles.card}>
        <Image style={styles.cardImage} source={{uri:content.image}}/>
        <View style={styles.cardText}>
          <Text style={styles.cardTitle} numberOfLines={1}>{content.title}</Text>
          <Text style={styles.cardDesc} numberOfLines={3}>{content.desc}</Text>
          <Text style={styles.cardDate}>{content.date}</Text>
        </View>
      </View>)
}

const styles = StyleSheet.create({

  card:{
    flex:1,
    //컨텐츠들을 가로로 나열
    //세로로 나열은 column <- 디폴트 값임 
    flexDirection:"row",
    margin:10,
    borderBottomWidth:0.5,
    borderBottomColor:"#eee",
    paddingBottom:10

  },
  cardImage: {
    flex:1,
    width:100,
    height:100,
    borderRadius:10,
  },
  cardText: {
    flex:2,
    flexDirection:"column",
    marginLeft:10,
  },
  cardTitle: {
    fontSize:20,
    fontWeight:"700"
  },
  cardDesc: {
    fontSize:15
  },
  cardDate: {
    fontSize:10,
    color:"#A6A6A6",
  }
})

다른 페이지에서 Card라는 컴포넌트를 호출해서 쓸 때 :

import Card from '../components/Card';

알고가야할 부분

JavaScript는 객체기반의 프로그래밍 언어로 변경불가능한 원시값을 제외한 함수,배열,정규 표현식 등은 모두 객체이다.

var Person = { name: "Lee", age: 20 };

객체는 0개 이상의 속성(property)으로 구성된 집합으로, 속성은 키(key)와 값(value)로 구성 -> 위와 같은 경우, Person이라는 객체는 name과 age라는 속성을 가지며, name과 age가 속성의 키라면, "Lee"와 20은 속성의 값을 의미한다.

props: 컴포넌트는, 데이터를 가진 하나의 'props' 객체 인자를 받은 후 엘리먼트를 반환한다. 이때 props는 속성을 나타내는 데이터로 컴포넌트에서 컴포넌트로 전달하는 데이터로 부모 컴포넌트가 자식 컴포넌트에 값을 전달할 때 사용하는 것으로 읽기 전용

useState: React 내에는 함수형 컴포넌트들을 위해 만들어진 API들의 집합인 React Hooks가 있는데, 그중에서도 가장 많이 사용되는게 useState.
컴포넌트에서 동적으로 변화되는 값을 state(상태)라고 하는데, 이를 적절히 활용하여 상태값만의 변경으로, 전체가 렌더링(새로고침)이되는 것이 아닌 바뀐 state의 값만 렌더링되는 장점을 가짐

import {useState} from 'react';
const [state, setState] = useState([0]);

state는 현재값, setState는 변경되는 값, 그리고 useState()안에는 기본적으로 초기값을 지정해 활용한다. (초기값은 숫자나 불린, 리스트 등)
useState라는 함수가 실행됨으로써 useState()내에 입력한 값이 state에 초기값으로 할당되고, 변경되는 값은 setState를 통하여 state에 할당된다.

function Card(){
	const [state, setState] = useState(1)
    const change = () => {
    	setState(4)
    }
    return(
    )
}

주의사항으로 useState는 그자체로 활용가능한 것이 아니여서, 위와 같이 다른 함수 내에서 정의를 하고, 활용해야한다.

  • state의 값을 변경하고 싶을때는 복사본을 만들어야한다.
var newState = state
// 값 복사가 아니라 값 공유
var newSate = [...state]
// 이렇게 값을 복사해서 사용해야함

useEffect: component가 렌더링(마운트 / 언마운트 / 업데이트의 이유로)될 때, 할 작업을 선택하도록 하는 Hook함수. 외부 API를 요청하거나, 반복작업 / 작업예약 등에 쓰인다.

  • mount: component가 처음 화면에서 보여질 때 (=새로고침 시)

  • unmount: component가 화면에서 사라질 때

  • update: 특정 props가 바뀌어 component가 업데이트될 때
import {useEffect} from 'react';
useEffect(()=>{}, [])
useEffect(()=>{}, [change])

기본적으로 첫번째 줄처럼 최초 렌더링시 실행되고, 두번째 줄처럼 change라는 변수를 설정시, 변수의 값이 변경시 실행된다!

setTimeout(()=>{
        setState(data)
        setReady(false)
    },1000)

위와같이 최초 로딩시 useEffect함수 내 setTime함수를 이용해, 1초(1000ms) 뒤 실행할 함수들을 지정해줄 수 있음(초기값은 설정이 되어있어야함)

stackNavigator: 컴포넌트에 페이지 기능을 부여하여 컴포넌트에서 컴포넌트로 이동을 가능하게 한다.

npm install @react-navigation/native @react-navigation/stack

npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view 
  • 구조(틀)

StackNavigator.js

import { createStackNavigator } from '@react-navigation/stack';

//페이지로 만든 컴포넌트들을 불러옵니다
import DetailPage from '../pages/DetailPage';
import MainPage from '../pages/MainPage';

//스택 네비게이션 라이브러리가 제공해주는 여러 기능이 담겨있는 객체를 사용합니다
const Stack = createStackNavigator();


const StackNavigator = () =>{
    return (
        //컴포넌트들을 페이지처럼 여기게끔 해주는 기능을 하는 네비게이터 태그를 선언합니다.
        //위에서 선언한 const Stack = createStackNavigator(); Stack 변수에 들어있는 태그를 꺼내 사용합니다.
        //Stack.Navigator 태그 내부엔 페이지(화면)를 스타일링 할 수 있는 다양한 옵션들이 담겨 있습니다.
        <Stack.Navigator
            screenOptions={{
                headerStyle: {
                    backgroundColor: "black",
                    borderBottomColor: "black",
                    shadowColor: "black",
                    height:100
                },
                headerTintColor: "#FFFFFF",
                headerBackTitleVisible: false
            }}
        >
            <Stack.Screen name="MainPage" component={MainPage}/>
            <Stack.Screen name="DetailPage" component={DetailPage}/>
        </Stack.Navigator>
    )
}

export default StackNavigator;

App.js

import React from 'react';
import {StatusBar} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';

import StackNavigator from './navigation/StackNavigator';

export default function App() {
  console.disableYellowBox = true;

  return (
    <NavigationContainer>
      <StatusBar style="black" />
      <StackNavigator />
    </NavigationContainer>
  );
}

NavigationContainer: 책
StackNavigator: 페이지를 쌓는것(Stack)
Stack.Screen: 페이지
Stack.Navigator: 책갈피
-> 두개의 파일로 구분되어있지만 App.js는 아래와 같은 구조를 가짐

export default function App() {
	return (
      <NavigationContainer>
        <StackNavigator>
          <Stack.Screen name="MainPage" component={MainPage}/>
          <Stack.Screen name="DetailPage" component={DetailPage}/>
        </Stack.Navigator>
      </NavigationContainer>
      )
  • 구조(활용):
//navigation 객체가 가지고 있는 두 함수(setOptions와 navigate)

//해당 페이지의 제목을 설정할 수 있음
navigation.setOptions({
   title:'나만의 꿀팁'
})

//Stack.screen에서 name 속성으로 정해준 이름을 지정해주면 해당 페이지로 이동하는 함수
navigation.navigate("DetailPage")

//name 속성을 전달해주고, 두 번째 인자로 딕셔너리 데이터를 전달해주면, Detail 페이지에서 
//두번째 인자로 전달된 딕셔너리 데이터를 route 딕셔너리로 로 받을 수 있음
navigation.navigate("DetailPage",{
  title: title
})


//전달받은 데이터를 받는 route 딕셔너리
//비구조 할당 방식으로 route에 params 객체 키로 연결되어 전달되는 데이터를 꺼내 사용
//navigate 함수로 전달되는 딕셔너리 데이터는 다음과 같은 모습이기 때문입니다.
/*
  {
		route : {
			params :{
				title:title
			}
		}
	}

*/
const { title} = route.params;

MainPage.js

export default function MainPage({navigation, route}) {
	const [cateState, setCateState] = useState([]);
	return (
    	<View style={styles.cardContainer}>
        {cateState.map((content, i) => {
          return <Card content={content} key={i} navigation={navigation}/>;
        })}
      </View>
    )}

Card.js

export default function Card({content, navigation}) {
 // MainPage로부터 content와 navigation이라는 props를 부여받음
  return (
    <TouchableOpacity
      onPress={() => {
        navigation.navigate('DetailPage', content);
      }}>
      // DetailPage에 content라는 prop을 전달함
      <Image source={{uri: content.image}} />
      <View>
        <Text>{content.title}</Text>
        <Text>{content.desc}</Text>
        <Text>{content.date}</Text>
      </View>
    </TouchableOpacity>
  );
}

DetailPage.js

export default function DetailPage({navigation, route}) {
// Card에서 content라는 데이터를 route라는 딕셔너리로 전달받음
  const [tip, setTip] = useState({
    idx: 9,
    category: '재테크',
    title: '렌탈 서비스 금액 비교해보기',
    image:
      'https://storage.googleapis.com/sparta-image.appspot.com/lecture/money1.png',
    desc: '요즘은 정수기, 공기 청정기, 자동차나 장난감 등 다양한 대여서비스가 활발합니다. 사는 것보다 경제적이라고 생각해 렌탈 서비스를 이용하는 분들이 늘어나고 있는데요. 다만, 이런 렌탈 서비스 이용이 하나둘 늘어나다 보면 그 금액은 겉잡을 수 없이 불어나게 됩니다. 특히, 렌탈 서비스는 빌려주는 물건의 관리비용까지 포함된 것이기에 생각만큼 저렴하지 않습니다. 직접 관리하며 사용할 수 있는 물건이 있는지 살펴보고, 렌탈 서비스 항목에서 제외해보세요. 렌탈 비용과 구매 비용, 관리 비용을 여러모로 비교해보고 고민해보는 것이 좋습니다. ',
    date: '2020.09.09',
  });

  useEffect(() => {
    console.log(route);
    navigation.setOptions({
      title: route.params.title,
      headerStyle: {
        backgroundColor: '#000',
        shadowColor: '#000',
      },
      headerTintColor: '#fff',
    });
    setTip(route.params);
  }, [navigation, route]);
profile
느리지만 굳세고 단단하게 성장하고픈 FE

0개의 댓글