커뮤니티
포인트
쿠폰
내 강의실
국비 신청 내역
증명서
계정
로그아웃
학습 질문
개발 일지
나의 활동
답변 완료
DetailPage에서의 상태관리에 대해서 질문이 있습니다.
[왕초보] 나만의 수익성 앱, 앱개발 종합반
4주차
북마크
김*규
댓글
11
추천
0
조회수
33
조회수
33
답변 완료

* 겪고 있는 문제 상황을 최대한 자세하게 작성해주세요.

* 문제 해결을 위해 어떤 시도를 해보았는지 구체적으로 함께 알려주세요.


안녕하세요. 혼자서 이해가 가지 않는 부분이 있어서 코드에 이것저것을 하며 실험을 해봤습니다.

제가 이해가 가지 않는 부분은 DetailPage에서 처음에는 tip이 기본 데이터였다가 어느 순간부터 tip이 서버에서 갖고 온DetailPage의 tip이 되는지 잘 이해가 안갔습니다.


그래서 console.log를 하며 tip이 변해가는 과정을 지켜봤습니다.

이제 tip이 어느 순간부터 바뀌게 되는지는 이해가 갔는데, useEffect의 동작 원리가 이해가 잘 가지 않습니다.

useEffect( ( )=>{ } ) 내부에서 console.log(tip)을 제일 마지막에 찍어봤을 때는 tip이 여전히 기본데이터였습니다.

useEffect를 나오고 나서부터는 tip이 서버에서 갖고온 데이터가 됐고요.


그래서 useEffect 내부의 firebase함수가 실행이 끝나기전에 비동기 진행 방식으로 처리가 돼서 useEffect내부의 console.log(tip)이 아직 기본데이터인가? 하는 마음에 async,await를 사용하여 프로그램을 돌려봤는데,

분명히 바깥쪽 console.log(tip)부분은 서버에서 갖고 온 팁이 됐지만, useEffect안쪽의 console.log(tip)부분은 여전히

기본 데이터입니다.


정리:

  1. useEffect 내부에서 setTip함수를 이용하여 tip의 값을 바꾸고 난 뒤 직후에 console.log(tip)을 하면 아직 기본데이터이다.
  2. useEffect 함수 바로 다음에 console.log를 찍어보면 바로 서버에서 갖고 온 데이터가 할당되어 있다.


useEffect 내부에서 어떠한 순서로 tip이 바뀌는지 알 수 있을까요?

왜 tip에 서버 정보를 넣었는데도 useEffect함수 내부에서는 아직 tip이 기본 데이터일까요?


##useEffect에는 의도적으로 async를 넣었습니다.


스파르타 즉문즉답




consle.log(tip,'hi!') 가 useEffect 내부에서 찍어본 tip이고, console.log(tip,'bye!')가 useEffect가 끝난 직후 찍어본 tip입니다.

import React, { useState, useEffect } from "react";
import {
  StyleSheet,
  Text,
  View,
  Image,
  ScrollView,
  TouchableOpacity,
  Alert,
  Share,
  Platform,
} from "react-native";
import * as Linking from "expo-linking";
import { firebase_db } from "../firebaseConfig";
import * as Application from "expo-application";
const isIOS = Platform.OS === "ios";


export default function DetailPage({ navigation, 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(async () => {
    console.log(route);


    navigation.setOptions({
      title: route.params.title,
      headerStyle: {
        backgroundColor: "#000",
        shadowColor: "#000",
      },
      headerTintColor: "#fff",
    });
    //넘어온 데이터는 route.params에 들어 있습니다.
    const { idx } = route.params;
    await firebase_db
      .ref("/tip/" + idx)
      .once("value")
      .then((snapshot) => {
        let tip = snapshot.val();
        setTip(tip);
      });
    console.log(tip, "hi!");
  }, []);
  console.log(tip, "bye!");
  const like = async () => {
    // like 방 안에
    // 특정 사용자 방안에
    // 특정 찜 데이터 아이디 방안에
    // 특정 찜 데이터 몽땅 저장!
    // 찜 데이터 방 > 사용자 방 > 어떤 찜인지 아이디
    let userUniqueId;
    if (isIOS) {
      let iosId = await Application.getIosIdForVendorAsync();
      userUniqueId = iosId;
    } else {
      userUniqueId = await Application.androidId;
    }


    console.log(userUniqueId);


    firebase_db
      .ref("/like/" + userUniqueId + "/" + tip.idx)
      .set(tip, function (error) {
        console.log(error);
        Alert.alert("찜 완료!");
      });
    console.log(tip);
  };


  const share = () => {
    Share.share({
      message: `${tip.title} \n\n ${tip.desc} \n\n ${tip.image}`,
    });
  };


  const link = () => {
    Linking.openURL("https://spartacodingclub.kr");
  };
  return (
    // ScrollView에서의 flex 숫자는 의미가 없습니다. 정확히 보여지는 화면을 몇등분 하지 않고
    // 화면에 넣은 컨텐츠를 모두 보여주려 스크롤 기능이 존재하기 때문입니다.
    // 여기선 내부의 컨텐츠들 영역을 결정짓기 위해서 height 값과 margin,padding 값을 적절히 잘 이용해야 합니다.
    <ScrollView style={styles.container}>
      <Image style={styles.image} source={{ uri: tip.image }} />
      <View style={styles.textContainer}>
        <Text style={styles.title}>{tip.title}</Text>
        <Text style={styles.desc}>{tip.desc}</Text>
        <View style={styles.buttonGroup}>
          <TouchableOpacity style={styles.button} onPress={() => like()}>
            <Text style={styles.buttonText}>팁 찜하기</Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.button} onPress={() => share()}>
            <Text style={styles.buttonText}>팁 공유하기</Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.button} onPress={() => link()}>
            <Text style={styles.buttonText}>외부 링크</Text>
          </TouchableOpacity>
        </View>
      </View>
    </ScrollView>
  );
}


const styles = StyleSheet.create({
  container: {
    backgroundColor: "#000",
  },
  image: {
    height: 400,
    margin: 10,
    marginTop: 40,
    borderRadius: 20,
  },
  textContainer: {
    padding: 20,
    justifyContent: "center",
    alignItems: "center",
  },
  title: {
    fontSize: 20,
    fontWeight: "700",
    color: "#eee",
  },
  desc: {
    marginTop: 10,
    color: "#eee",
  },
  buttonGroup: {
    flexDirection: "row",
  },
  button: {
    width: 90,
    marginTop: 20,
    marginRight: 10,
    marginLeft: 10,
    padding: 10,
    borderWidth: 1,
    borderColor: "deeppink",
    borderRadius: 7,
  },
  buttonText: {
    color: "#fff",
    textAlign: "center",
  },
});




취소
 공유
취소
댓글 0
댓글 알림
나의얼굴