지역별로 해당 검색어에 맞는 지역의 언어치료센터 리스트를 불러오는 것 까지 성공했다.
코드가 좀 지저분해진 것 같긴 하지만 일단은 구현 먼저! 코드 정리는 나중에!ㅋㅋㅋ
![](https://t1.daumcdn.net/keditor/emoticon/friends1/large/011.gif)
[카테고리 기능이 구현된 모습]
오늘은 예전에 만들어 놓은 상세보기 페이지를 이용해서
메인에서 리스트를 클릭하면 해당 상세보기 페이지로 이동하는 것을 구현할 예정이다.
1. 네비게이션을 이용하기 위한 기본 라이브러리 설치하기
react-navigation 공식문서 : https://reactnavigation.org
React Navigation | React Navigation
Routing and navigation for your React Native apps
reactnavigation.org
@첫번째 설치
yarn add @react-navigation/native
@두번째 설치
expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view
@createStackNavigator 설치
yarn add @react-navigation/stack
2. navigation 폴더를 만들고 StackNavigator.js 파일 만들기
[ StackNavigation.js ]
import React from "react";
//설치한 스택 네비게이션 라이브러리를 가져옴
import { createStackNavigator } from "@react-navigation/stack";
//페이지로 만든 컴포넌트들을 불러옴
import Detail from "../pages/Detail";
import Main from "../pages/Main";
//스택 네비게이션 라이브러리가 제공해주는 여러 기능이 담겨있는 객체를 사용
//그래서 이렇게 항상 상단에 선언하고 시작하는게 규칙!
const Stack = createStackNavigator();
const StackNavigator = () => {
return (
//컴포넌트들을 페이지로 만들어주는 네비게이터(Navigator) 태그 선언
//위에서 선언한 Stack 변수에 들어있는 태그를 꺼내 사용
//Stack.Navigator 태그 내부엔 페이지(화면)를 스타일링 할 수 있는 다양한 옵션들이 있음 (여기선 사용안함)
<Stack.Navigator
// screenOptions={{
// headerStyle: {
// backgroundColor: "black",
// borderBottomColor: "black",
// shadowColor: "black",
// height: 100,
// },
// headerTintColor: "#FFFFFF",
// headerBackTitleVisible: false,
// }}
>
{/* 컴포넌트를 페이지로 만들어주는 엘리먼트에 끼워 넣기 = 이 자체로 페이지 기능 가능*/}
<Stack.Screen name="Main" component={Main} />
<Stack.Screen name="Detail" component={Detail} />
</Stack.Navigator>
);
};
export default StackNavigator;
아래쪽의 <Stack.Screen~~~>에 name으로 정해둔 이름을 가지고 나중에 페이지 이동을 한다.
※ name은 반드시 있어야 함!
3. 최상단 컴포넌트(App.js)에다 네비게이션 기능 달아주기
[ App.js ]
import React from "react";
// 네비게이션 달아줄거니까 이제 페이지 컴포넌트들 안 불러와도 됨.
// import Main from "./pages/Main";
// import Detail from "./pages/Detail";
// 네비게이션 도구들 불러옴.
import { NavigationContainer } from "@react-navigation/native";
import StackNavigator from "./navigation/StackNavigator";
export default function App() {
return (
// <Main />
// <Detail />
<NavigationContainer>
<StackNavigator />
</NavigationContainer>
);
}
App.js에다가 네비게이션을 달아줘야 앱 어디서든지 원하는 페이지 이동이 가능하다.
4. 스택네비게이션으로 페이지 이동하기
Stack.screen에 등록된 모든 페이지 컴포넌트들은 navigation과 route라는 딕셔너리(혹은 객체)를 속성으로 넘겨받아서 사용할 수 있다.
@ navigation
//해당 페이지의 제목을 설정할 수 있음
navigation.setOptions({
title:'메인입니다.'
})
//Stack.screen에서 name 속성으로 정해준 이름을 지정해주면 해당 페이지로 이동하는 함수
navigation.navigate("Detail")
//name 속성을 전달해주고, 두 번째 인자로 딕셔너리 데이터를 전달해주면, Detail 페이지에서
//두번째 인자로 전달된 딕셔너리 데이터를 route 딕셔너리로 로 받을 수 있음
navigation.navigate("Detail",{
title: title
})
@ route
//전달받은 데이터를 받는 route 딕셔너리
//비구조 할당 방식으로 route에 params 객체 키로 연결되어 전달되는 데이터를 꺼내 사용
//navigate 함수로 전달되는 route 데이터는 아래와 같은 모습
{
route : {
params :{
title:title
}
}
}
const { title} = route.params;
Card에서 Detail로 이동할 때 Main으로부터 넘겨받은 content도 같이 넘겨준다.
[ Card.js ]
import React from "react";
import { StyleSheet, Text, View, TouchableOpacity } from "react-native";
export default function Card({ content, navigation }) { // 보내야 되니까 content 추가
return (
<TouchableOpacity
style={styles.cardContainer}
onPress={() => {
navigation.navigate("Detail", content); // navigation과 함께 content도 넘겨준다.
}}
>
<View style={styles.card1}>
<Text style={styles.cardName}>{content.name}</Text>
<Text style={styles.cardRating}>평점: 5점</Text>
</View>
<Text style={styles.cardAddress} numberOfLines={1}>
{content.address}
</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
cardContainer: {
marginTop: 10,
width: "95%",
alignSelf: "center",
borderBottomWidth: 1,
borderBottomColor: "#eee",
paddingBottom: 10,
},
card1: {
flexDirection: "row",
justifyContent: "space-between",
},
cardName: {
fontSize: 20,
fontWeight: "bold",
marginTop: 10,
marginBottom: 10,
},
cardRating: {
fontSize: 15,
marginTop: 10,
marginBottom: 10,
},
cardAddress: {
fontSize: 15,
},
});
[ Detail.js ]
import React, { useState, useEffect } from "react";
import MapView from "react-native-maps";
import {
StyleSheet,
Text,
View,
ScrollView,
TouchableOpacity,
} from "react-native";
export default function Detail({ navigation, route }) { // navigation하고 route를 받는다.
const [center, setCenter] = useState({});
useEffect(() => {
navigation.setOptions({ // 받은 navigation의 setOptions로
title: route.params.name, // route.params.name을 꺼낸다.
});
setCenter(route.params); // setCenter함수를 사용해서 center의 값을 route.params로 지정한다.
}, []);
return (
<View style={styles.container}>
<View style={styles.localView}>
<Text style={styles.localSi}>대전광역시</Text>
<Text style={styles.localGu}>유성구</Text>
</View>
<View style={styles.textView}>
<View style={styles.nameRateView}>
<Text style={styles.name}>{center.name}</Text> // 위의 center에서 name을 꺼내 보여준다.
<Text style={styles.rating}>별점: 5점</Text>
</View>
<View style={styles.addressView}>
<Text style={styles.address} numberOfLines={1}>
{center.address}
</Text>
</View>
</View>
<View style={styles.mapView}>
<Text>지도</Text>
<MapView style={styles.map} />
</View>
<View style={styles.buttonView}>
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText} onPress={() => popup()}>
찜하기
</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText}>공유하기</Text>
</TouchableOpacity>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginLeft: 10,
marginRight: 10,
backgroundColor: "#CBE7F5",
},
localView: {
width: "100%",
flexDirection: "row",
paddingBottom: 10,
marginTop: 50,
backgroundColor: "#CBE7F5",
},
localSi: {
fontWeight: "bold",
fontSize: 20,
alignSelf: "flex-start",
},
localGu: {
fontWeight: "bold",
fontSize: 20,
alignSelf: "flex-start",
marginLeft: 10,
},
textView: {
flex: 1,
paddingTop: 20,
backgroundColor: "orange",
},
nameRateView: {
flexDirection: "row",
justifyContent: "space-between",
},
name: {
fontSize: 20,
marginTop: 10,
fontWeight: "bold",
backgroundColor: "red",
},
rating: {
fontSize: 20,
marginTop: 10,
fontWeight: "bold",
backgroundColor: "lightgray",
},
addressView: {},
address: {
fontSize: 20,
},
mapView: {
flex: 3,
backgroundColor: "green",
},
buttonView: {
flex: 1,
flexDirection: "row",
justifyContent: "space-between",
marginLeft: 50,
marginRight: 50,
backgroundColor: "pink",
},
button: {
width: 120,
height: 50,
marginTop: 20,
padding: 10,
borderWidth: 1,
borderColor: "deeppink",
borderRadius: 7,
},
buttonText: {
color: "#fff",
textAlign: "center",
fontSize: 18,
},
});
[결과]
디테일까지 연결해놨으니 이제 인트로 페이지를 구현해 볼 생각이다.
지금은 대한민국 전체 시도를 카테고리로 보여주고 있어서 제주도의 언어치료센터를 찾으려면 끝까지 스크롤을 해야하는 불편함이 있다.
그래서 앱을 실행하자마자 인트로 페이지를 보여주고, 본인이 사는 곳의 지역을 선택하도록 하면 조금 더 깔끔한 UI를 만들 수 있을 것 같다.
생각하고 있는 건 유저의 현재 위치를 파악해서 근처에 있는 언어치료센터를 보여주는 것인데
아직 쌩초보라 갈길이 멀기 때문에...ㅠㅠㅠㅠ
![](https://t1.daumcdn.net/keditor/emoticon/friends1/large/012.gif)
내가 할 수 있는 범위보다 조금 더 발전된 기능을 추가하다 보면 목표까지 갈 수 있으리라 생각한다.
화이팅!
'앱 개발' 카테고리의 다른 글
[react-native] 지역 선택 : select되면 함수로 state 변경해서 안내 글자 바꾸기 (0) | 2022.06.21 |
---|---|
[react-native] NativeBase 설치 및 처음 시작하기 (0) | 2022.06.20 |
[react-native] 특정 문자를 포함한 데이터를 찾아 카테고리별 다른 화면 보여주기 (0) | 2022.06.15 |
[react native] 엑스포 Expo object console 값 보는 법 (0) | 2022.06.14 |
[react-native] ScrollView로 감싸져 있는 View의 flex가 안 먹힌다...! (0) | 2022.06.08 |
댓글