search.js

김종민·2022년 5월 31일
0

insta-native

목록 보기
21/36

들어가기
insta에서 사진의 caption에 있는 단어들을 근거로,
검색을 해서 사진을 찾아서 뿌려줄 수 있다.
사진을 클릭 하면, 사진을 feed에 나오는 사진처럼 like, comment, 등등을 볼 수 있다.

1. screens/Search.js


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>
  )
}

2. components/DisimssKeyboard.js

화면 바깥을 클릭했을때, 키보드가 사라지는 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>
  )
}
profile
코딩하는초딩쌤

0개의 댓글