들어가기
insta에서 사진의 caption에 있는 단어들을 근거로,
검색을 해서 사진을 찾아서 뿌려줄 수 있다.
사진을 클릭 하면, 사진을 feed에 나오는 사진처럼 like, comment, 등등을 볼 수 있다.
import React, { useEffect } from 'react'
import {
ActivityIndicator,
Image,
Text,
TextInput,
useWindowDimensions,
View,
TouchableOpacity,
FlatList,
} from 'react-native'
import styled from 'styled-components/native'
import { logUserOut } from '../apollo'
import { useForm } from 'react-hook-form'
import DismissKeyboard from '../components/DismissKeyboard'
import { gql, useLazyQuery } from '@apollo/client'
import { useNavigation } from '@react-navigation/native'
const SEARCH_PHOTOS = gql` ///query searchPhotos로 keyword로 검색해서
/// 사진의 id와 file을 불러 오게 한다.
query searchPhotos($keyword: String!) {
searchPhotos(keyword: $keyword) {
id
file
}
}
`
const MessageContainer = styled.View`
justify-content: center;
align-items: center;
flex: 1;
`
const MessageText = styled.Text`
margin-top: 15px;
color: white;
font-weight: 600;
`
///검색창을 만드는것, TextInput가 됨을 주의깊게 볼것!!
const Input = styled.TextInput`
background-color: rgba(255, 255, 255, 1);
color: black;
width: ${(props) => props.width / 1.5}px;
padding: 5px 10px;
border-radius: 7px;
`
export default function Search({ navigation }) {
const numColumns = 4
const { width } = useWindowDimensions() ///화면의 width를 알기위해 useDimentions사용
const { setValue, register, watch, handleSubmit } = useForm()
///검색어 입력을 위해서 useForm사용.
const [startQueryFn, { loading, data, called }] = useLazyQuery(SEARCH_PHOTOS)
///useLazyQuery는 엔터키를 눌렀을떄, Query를 실행하게 하는 query
///useQuery는 화면이 rendering되면 바로 실행됨.
const onValid = ({ keyword }) => {
startQueryFn({
variables: {
keyword,
},
})
}
///Input에서 handleSubmit이 되면 startQueryFn에 keyword를 보내줌.
const SearchBox = () => (
<Input
width={width}
style={{ backgroundColor: 'white' }}
placeholderTextColor="rgba(0,0,0,0.8)"
placeholder="Search Photos"
autoCapitalize="none"
returnKeyType="search"
returnKeyLabel="Search"
autoCorrect={false}
onChangeText={(text) => setValue('keyword', text)}
onSubmitEditing={handleSubmit(onValid)}
/>
)
///화면 맨 상단에 검색창을 만들어줌
///onChangeText부분과 onSubmitEditing부분을 주의깊게 볼것.
useEffect(() => {
navigation.setOptions({
headerTitle: SearchBox,
})
register('keyword', { required: true, minLength: 3 })
}, [])
///useEffect를 이용해서, setOptions를 이용해서, screen의 header부분에 검색창을 넣음.
///register부분을 꼭 명심할 것!!!!
console.log(data)
const renderItem = ({ item: photo }) => (
<TouchableOpacity
onPress={() => navigation.navigate('Photo', { photoId: photo.id })}
>
<Image
source={{ uri: photo.file }}
style={{ width: width / numColumns, height: 100, margin: 1 }}
/>
</TouchableOpacity>
)
///FlatList에 사용될 renderItem 함수를 만들어줌.
///클릭시 Photo screen으로 이동되며, photoId를 route로 보내준다는 것을 명심할것.
return (
<DismissKeyboard> =>DismissKeyboard는 component로 만들어줌, 아래부분 참고
<View style={{ flex: 1, backgroundColor: 'black' }}>
{loading ? (
<MessageContainer>
<ActivityIndicator size="large" />
<MessageText>Searching...</MessageText>
</MessageContainer>
) : null}
{!called ? ( called==> useForm()에서 불러주는것, called되지않을떄, 설정
<MessageContainer>
<MessageText>Search by keyword</MessageText>
</MessageContainer>
) : null}
{data?.searchPhotos !== undefined &&
data?.searchPhotos?.length === 0 ? (
<MessageContainer>
<MessageText>Could not find anything.</MessageText>
</MessageContainer>
) : (
<FlatList
numColumns={numColumns} ==>grid와 같은 역활, 한줄에 몇개씩 뿌릴것인지~
data={data?.searchPhotos}
keyExtractor={(photo) => '' + photo.id}
renderItem={renderItem}
/>
)}
</View>
</DismissKeyboard>
)
}
화면 바깥을 클릭했을때, 키보드가 사라지는 component, 많은 screen에서 사용될 것이라서
따로, component로 만들어 놓음.
import React from 'react'
import { Keyboard, Platform, TouchableWithoutFeedback } from 'react-native'
export default function DismissKeyboard({ children }) {
const dismissKeyboard = () => {
Keyboard.dismiss()
}
return (
<TouchableWithoutFeedback
style={{
flex: 1,
}}
onPress={dismissKeyboard}
disabled={Platform.OS === 'web'}
>
{children}
</TouchableWithoutFeedback>
)
}