앱 개발 일지_ React

윤승환·2022년 1월 26일
0

Sparta_APP

목록 보기
3/7
post-custom-banner

React 필수 지식

-> 피라미드 형태의 구조를 이룬다.

  • 컴포넌트(Component) : 정해진 element를 사용하여 만든 화면의 일부분 -> 코드 재사용 용이
  • 상태(State, useState) : 컴포넌트에서 데이터를 오지하고 관리하기 위한 유일한 방법 == 사용할 데이터!
  • 속성(Props) : 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달하는 방식 == 데이터 전달!
  • useEffect : 화면에 컴포넌트가 그려지면 처음 실행해야 하는 함수들을 모아두는 곳.

컴포넌트화


MainPage에서 다음과 같이 import해서 사용한다


import Card from '../components/Card';
tip.map((content,i)=>{
            // return (<View style={styles.card} key={i}>
            //   <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>)
            return (<Card content={content} key={i}/>)
          })

컴포넌트화 된 Card

//Card_code
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",
  }
})

속성

  • 컴포넌트에 데이터를 전달해주는 것
  • 전달 모습은 마치 key = {value} 형태

상태

  • 컴포넌트 안에서 존재한다.
  • 데이터 = 상태
  • React Library에서 제공해주는 함수인 useState로 초기화를 하고 setState로 정/변경할 수 있다.
import React,{useState,useEffect} from 'react';
  • UI = component(state) 데이터가 변경되면 화면이 바뀐다

useEffect

  • 데이터를 준비할 때 사용한다.
  • 무슨 말이냐면,, 사용자가 요청을 할 때, 해당 Page가 데이터를 너무 많이 필요로 한다면 요청에 대한 응답이 늦어질 수 있다. 따라서 데이터를 먼저 받은 후 상태(State)에 반영한다는 것을 의미한다.

    1. 화면이 그려진다
    2. useEffect가 데이터를 준비한다.
    3. 상태 데이터가 업데이트 되었으니 화면이 다시 그려진다.

useEffect(()=>{
  ...화면이 그려진 다음 가장 먼저 실행되어야 할 코드 작성
  } , [] )
  

Ex)

export default function MainPage() {
  //useState 사용법
	//[state,setState] 에서 state는 이 컴포넌트에서 관리될 상태 데이터를 담고 있는 변수
  //setState는 state를 변경시킬때 사용해야하는 함수

  //모두 다 useState가 선물해줌
  //useState()안에 전달되는 값은 state 초기값
  //위치가 중요한거지 변수 명이 정해져있는 것이 아님.
  const [state,setState] = useState([])
	

	//하단의 return 문이 실행되어 화면이 그려진다음 실행되는 useEffect 함수
  //내부에서 data.json으로 부터 가져온 데이터를 state 상태에 담고 있음
  useEffect(()=>{
    setState(data)
  },[])

처음에 useState([])가 빈 list이기때문에, state에 초기값설정이 빈 list로 설정될 것이다. -> 오류의 원인
또한, setState변수는 데이터 업데이트에 쓰이는 것인데, 아래 setState(data)로 업데이트 될 것이다.

이러한 오류를 해결하기 위해서는,, Loading~ 화면을 구축한다.

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

export default function Loading(){
    return(<View style={styles.container}><Text style={styles.title}>준비중입니다...</Text></View>)
}


const styles = StyleSheet.create({
    container: {
        //앱의 배경 색
        flex:1,
        justifyContent:'center',
        alignItems:'center',
        backgroundColor: '#fdc453',
    },
    title: {
        fontSize:20,
        fontWeight:'700'
    }

})

Loading화면 불러오는 방법(feat.삼항연산자)

  • 두 가지의 상태를 저장하여 활용한다.
    1.state와 ready라는 두가지 상태를 설정
    2.ready의 초기값을 true로 설정하여 랜더링을 loading으로 함.
    3.useEffect함수를 이용하여 state의 상태를 업데이트하고, ready값을 False로 업데이트.
    4.다음 랜더링 부터는 loading이 아닌 main컴포넌트가 실행될 것임.
import React,{useState,useEffect} from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native';

const main = 'https://storage.googleapis.com/sparta-image.appspot.com/lecture/main.png'
import data from '../data.json';
import Card from '../components/Card';
import Loading from '../components/Loading';
export default function MainPage() {
  //useState 사용법
	//[state,setState] 에서 state는 이 컴포넌트에서 관리될 상태 데이터를 담고 있는 변수
  //setState는 state를 변경시킬때 사용해야하는 함수

  //모두 다 useState가 선물해줌
  //useState()안에 전달되는 값은 state 초기값
  const [state,setState] = useState([])
	

	//하단의 return 문이 실행되어 화면이 그려진다음 실행되는 useEffect 함수
  //내부에서 data.json으로 부터 가져온 데이터를 state 상태에 담고 있음
  const [ready,setReady] = useState(true)

  useEffect(()=>{
	   
		//뒤의 1000 숫자는 1초를 뜻함
    //1초 뒤에 실행되는 코드들이 담겨 있는 함수
    setTimeout(()=>{
        setState(data)
        setReady(false)
    },1000)
 
    
  },[])

  //data.json 데이터는 state에 담기므로 상태에서 꺼내옴
  let tip = state.tip;
  let todayWeather = 10 + 17;
  let todayCondition = "흐림"
  //return 구문 밖에서는 슬래시 두개 방식으로 주석
  return ready ? <Loading/> :  (
    /*
      return 구문 안에서는 {슬래시 + * 방식으로 주석
    */
    <ScrollView style={styles.container}>
      <Text style={styles.title}>나만의 꿀팁</Text>
			 <Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition} </Text>
      <Image style={styles.mainImage} source={{uri:main}}/>
      <ScrollView style={styles.middleContainer} horizontal indicatorStyle={"white"}>
        <TouchableOpacity style={styles.middleButton01}><Text style={styles.middleButtonText}>생활</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton02}><Text style={styles.middleButtonText}>재테크</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton03}><Text style={styles.middleButtonText}>반려견</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton04}><Text style={styles.middleButtonText}>꿀팁 찜</Text></TouchableOpacity>
      </ScrollView>
      <View style={styles.cardContainer}>
         {/* 하나의 카드 영역을 나타내는 View */}
         {
          tip.map((content,i)=>{
            return (<Card content={content} key={i}/>)
          })
        }
        
      </View>
   
    </ScrollView>)
}

ex) 응용 code(카테고리 설정)


import React,{useState,useEffect} from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native';

const main = 'https://storage.googleapis.com/sparta-image.appspot.com/lecture/main.png'
import data from '../data.json';
import Card from '../components/Card';
import Loading from '../components/Loading';
export default function MainPage() {
  //useState 사용법
	//[state,setState] 에서 state는 이 컴포넌트에서 관리될 상태 데이터를 담고 있는 변수
  //setState는 state를 변경시킬때 사용해야하는 함수

  //모두 다 useState가 선물해줌
  //useState()안에 전달되는 값은 state 초기값
  const [state,setState] = useState([])
  const [cateState,setCateState] = useState([])

	//하단의 return 문이 실행되어 화면이 그려진다음 실행되는 useEffect 함수
  //내부에서 data.json으로 부터 가져온 데이터를 state 상태에 담고 있음
  const [ready,setReady] = useState(true)

  useEffect(()=>{
	   
		//뒤의 1000 숫자는 1초를 뜻함
    //1초 뒤에 실행되는 코드들이 담겨 있는 함수
    setTimeout(()=>{
        setState(data.tip)
        setCateState(data.tip)
        setReady(false)
    },1000)
 
    
  },[])
  
  //state를 사용하여 상태변경을 유지할 수 있다.
  const category = (cate) => {
    if(cate == "전체보기"){
        //전체보기면 원래 꿀팁 데이터를 담고 있는 상태값으로 다시 초기화
        setCateState(state)
    }else{
        setCateState(state.filter((d)=>{
            return d.category == cate
        }))
    }
}

  //data.json 데이터는 state에 담기므로 상태에서 꺼내옴
  // let tip = state.tip;
  let todayWeather = 10 + 17;
  let todayCondition = "흐림"
  //return 구문 밖에서는 슬래시 두개 방식으로 주석
  return ready ? <Loading/> :  (
    /*
      return 구문 안에서는 {슬래시 + * 방식으로 주석
    */
    <ScrollView style={styles.container}>
      <Text style={styles.title}>나만의 꿀팁</Text>
			 <Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition} </Text>
      <Image style={styles.mainImage} source={{uri:main}}/>
      <ScrollView style={styles.middleContainer} horizontal indicatorStyle={"white"}>
      <TouchableOpacity style={styles.middleButtonAll} onPress={()=>{category('전체보기')}}><Text style={styles.middleButtonTextAll}>전체보기</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton01} onPress={()=>{category('생활')}}><Text style={styles.middleButtonText}>생활</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton02} onPress={()=>{category('재테크')}}><Text style={styles.middleButtonText}>재테크</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton03} onPress={()=>{category('반려견')}}><Text style={styles.middleButtonText}>반려견</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton04} onPress={()=>{category('꿀팁 찜')}}><Text style={styles.middleButtonText}>꿀팁 찜</Text></TouchableOpacity>
      </ScrollView>
      <View style={styles.cardContainer}>
         {/* 하나의 카드 영역을 나타내는 View */}
         {
          cateState.map((content,i)=>{
            return (<Card content={content} key={i}/>)
          })
        }
        
      </View>
   
    </ScrollView>)
}
post-custom-banner

0개의 댓글