• 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    해결됨

구매버튼 클릭 시 soldout 구현 부분(상품 블러 처리)

23.07.25 17:04 작성 조회수 143

0

상품 상세 페이지에서 구매 버튼을 누르게 되면,

  • 해당 상품의 soldout값이 1로 바뀌게고 적용 완료.

  • 그 이후 자동으로 구매 버튼이 회색으로 다시 바뀌겠끔도 구현 완료

 

그 이후 뒷 페이지로 돌아갔을 때, 상품 목록에서 blur처리 되는 기능이 구현되지 않아 이 방법이 궁금합니다.

뒤로가기 버튼을 눌렀을 때는 해당 페이지가 새로 불러와지는 로직이 아닌가요?

 

// Main페이지 코드

import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, View, Image, ScrollView, Dimensions, TouchableOpacity, Alert } from "react-native";
import React, {useEffect, useState} from "react";
import axios from "axios";
import dayjs from "dayjs"
import relativeTime from "dayjs/plugin/relativeTime"
import "dayjs/locale/ko"
import Carousel from "react-native-reanimated-carousel"

import { API_URL } from "../config/constants";
import AvatarImage from "../assets/icons/avatar.png";

dayjs.extend(relativeTime);
dayjs.locale("ko");

export default function MainScreen(props) {

    const [products, setProducts] = useState([]);
    const [banners, setBanners] = useState([]);

    const getProduct = () => {
        axios
            .get(`${API_URL}/products`)
            .then((result) => {
                console.log(result);
                setProducts(result.data.products)
            })
            .catch((error) => {
                console.error(error);
            });
    }

    useEffect(() => {
        
        getProduct();
        
        axios
        .get(`${API_URL}/banners`)
        .then((result) => {
          setBanners(result.data.banners);
        })
        .catch((error) => {
          console.error(error);
        })

    }, []);

    return (
        <View style={styles.container}>
            <ScrollView>
                <Carousel
                    data={banners}
                    width={Dimensions.get("window").width}
                    height={200}
                    autoPlay={true}
                    sliderWidth={Dimensions.get("window").width}
                    itemWidth={Dimensions.get("window").width}
                    itemHeight={200}
                    renderItem={(obj) => {
                        return (
                            <TouchableOpacity onPress={() => { Alert.alert("배너 클릭"); }} >
                                <Image style={styles.bannerImage} source={{ uri: `${API_URL}/${obj.item.imageUrl}`}} resizeMode="contain" />
                            </TouchableOpacity>
                        );
                    }}
                />
                <Text style={styles.Headline}>판매되는 상품들</Text>
                <View sytle={styles.productList}>
                    {products.map((product, index) => {
                        return (
                            <TouchableOpacity onPress={() => {
                                props.navigation.navigate("Product", {
                                    id: product.id
                                })
                            }}>
                            <View style={styles.productCard}>
                                {product.soldout === 1 && (
                                    <View style={styles.productBlur} />
                                )}
                                <View>
                                    <Image
                                        style={styles.productImage}
                                        source={{
                                            uri: `${API_URL}/${product.imageUrl}`,
                                        }}
                                        resizeMode={"contain"}
                                    />
                                </View>
                                <View style={styles.productContents}>
                                    <Text sytle={styles.productName}>
                                        {product.name}
                                    </Text>
                                    <Text sytle={styles.productPrice}>
                                        {product.price}원
                                    </Text>
                                    <View style={styles.productFooter}>
                                        <View style={styles.productSeller}>
                                            <Image
                                                style={styles.productAvatar}
                                                source={AvatarImage}
                                            />
                                            <Text
                                                style={styles.productSellerName}
                                            >
                                                {product.seller}
                                            </Text>
                                        </View>
                                        <Text style={styles.productDate}>
                                            {dayjs(product.createdAt).fromNow()}
                                        </Text>
                                    </View>
                                </View>
                            </View>
                            </TouchableOpacity>
                        );
                    })}
                </View>
            </ScrollView>
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: "#fff",
        padding: 32,
    },

    productCard: {
        width: 320,
        borderColor: "rgb(230,230,230)",
        borderWidth: 1,
        borderRadius: 16,
        backgroundColor: "white",
        marginBottom: 8,
    },

    productImage: {
        width: "100%",
        height: 210,
    },
    productContents: {
        padding: 8,
    },

    productSeller: {
        flexDirection: "row",
        alignItems: "center",
    },

    productAvatar: {
        width: 24,
        height: 24,
    },

    productFooter: {
        flexDirection: "row",
        justifyContent: "space-between",
        alignItems: "center",
        marginTop: 12,
    },

    productName: {
        fontSize: 16,
    },

    productPrice: {
        fontSize: 18,
        fontWeight: "600",
        marginTop: 8,
    },

    productSellerName: {
        fontSize: 16,
    },

    productDate: {
        fontSize: 16,
    },

    productList: {
        alignItems: "center",
    },

    Headline: {
        fontSize: 24,
        fontWeight: "800",
        marginBottom: 24,
    },

    productBlur: {
        position: "absolute",
        top: 0,
        bottom: 0,
        left: 0,
        right: 0,
        backgroundColor : "#ffffffa6",
        zIndex: 999
    },

    bannerImage: {
      width: "90%",
      height: 200,
    },

    safeAreaView: {
      flex: 1,
      backgroundColor: "#fff"

    }
});

 

 

// Product 화면 코드

import axios from "axios";
import React, { useEffect, useState } from "react"
import {Image, ActivityIndicator, StyleSheet, View, Text, TouchableOpacity, Alert, ScrollView} from "react-native"
import { API_URL } from "../config/constants";
import Avatar from "../assets/icons/avatar.png"
import dayjs from "dayjs"


export default function ProductScreen(props){

    const {id} = props.route.params;

    const [product, setProduct] = useState(null);


    const getProduct = () => {
        axios.get(`${API_URL}/products/${id}`)
        .then((result) => {
            console.log("product result : ", result.data);
            setProduct(result.data.product);
        })
        .catch((error) => {
            console.error(error);
        })
    }


    useEffect(() => {
        getProduct();
    }, []);

    const onPressButton = () => {
        if(product.soldout !== 1) {
            axios.post(`${API_URL}/purchase/${id}`)
            .then((result) => {
                Alert.alert("구매가 완료되었습니다.");
                getProduct();
            })
            .catch((error) => {
                Alert.alert(`에러가 발생했습니다. ${error.message}`);
            })
        }
    }


    if(!product){
        return <ActivityIndicator />
    }


    return (
        <View style={styles.container}>
            <ScrollView>
                <View>
                    <Image style={styles.productImage} source={{uri: `${API_URL}/${product.imageUrl}`}} resizeMode="contain" />
                </View>
                <View style={styles.productSection}>
                    <View style={styles.productSeller}>
                        <Image style={styles.avatarImage} source={Avatar} />
                        <Text>{product.seller}</Text>
                    </View>
                    <View style={styles.divider} />
                    <View>
                        <Text style={styles.productName}>{product.name}</Text>
                        <Text style={styles.productPrice}>{product.price} 원</Text>
                        <Text style={styles.productDate}>{dayjs(product.createAt).format("YYYY년 MM월 DD일")}</Text>
                        <Text style={styles.productDescription}>{product.description}</Text>

                    </View>
                </View>
            </ScrollView>
            <TouchableOpacity onPress={onPressButton}>
                <View style={product.soldout ===1 ? styles.purchaseDisabled : styles.purchaseButton}>
                    <Text style={styles.purchaseText}>{product.soldout === 1 ? "구매완료" : "구매하기"}</Text>
                </View>
            </TouchableOpacity>
        </View>
            
    )
}


const styles = StyleSheet.create({

    container: {
        flex: 1,
        backgroundColor: "#fff"
    },

    productImage: {
        width: "100%",
        height: 300
    },

    productSeller: {
        flexDirection: "row",
        alignItems: "center"
    },

    avatarImage: {
        width: 50,
        height: 50,
    },

    productSection: {
        padding: 16
    },

    divider: {
        backgroundColor: "#e9ecef",
        height: 1,
        marginVertical: 16
    },

    productName: {
        fontSize: 20,
        fontWeight: "400"
    },

    productPrice: {
        fontSize: 18,
        fontWeight: "700",
        marginTop: 8
    },

    productDate: {
        fontSize:14,
        marginTop: 4,
        color: "rgb(204,204,204)"
    },

    productDescription: {
        marginTop : 16,
        fontSize: 17
    },

    purchaseButton: {
        position: "absolute",
        bottom: 0,
        left: 0,
        right: 0,
        height: 60,
        backgroundColor: "rgb(255,80,88)",
        alignItems : "center",
        justifyContent: "center"
    },

    purchaseText : {
        color: "white",
        fontSize: 20,
    },

    purchaseDisabled: {
        position: "absolute",
        bottom: 0,
        left: 0,
        right: 0,
        height: 60,
        backgroundColor: "gray",
        alignItems : "center",
        justifyContent: "center"

    }




})

답변 1

답변을 작성해보세요.

1

모바일에서는 웹과 다르게 뒤로가기를 눌렀을 때는 다시 화면이 렌더링되지는 않을 거예요. 뒤로가기를 눌렀을 때 api 호출을 다시 하도록 수정이 되어야 합니다.

이때는 `useFocusEffect` 를 사용해보시면 문제가 해결될 것 같아요. 아래 사이트를 참고해보셔도 좋을 것 같네요!

https://hyojin96.tistory.com/entry/React-Navigation-%ED%99%94%EB%A9%B4-%ED%8F%AC%EC%BB%A4%EC%8A%A4-%EA%B0%90%EC%A7%80-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-useFocusEffect-useIsFocused