이제 SearchHeader 컴포넌트 UI를 구성하겠습니다.
components/SearchHeader.js
import React from 'react';
import {
View,
StyleSheet,
Text,
useWindowDimensions,
Pressable,
TextInput,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
function SearchHeader() {
const {width} = useWindowDimensions();
return (
<View style={[styles.block, {width: width - 32}]}>
<TextInput
style={styles.input}
placeholder={'검색어를 입력하세요'}
autoFocus
/>
<Pressable
style={({pressed}) => [styles.button, pressed && {opacity: 0.5}]}>
<Icon name={'cancel'} size={20} color={'#9e9e9e'} />
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
block: {
flexDirection: 'row',
alignItems: 'center',
},
input: {
flex: 1,
},
button: {
marginLeft: 8,
},
});
export default SearchHeader;
TextInput에 autoFocus를 사용하여
이 컴포넌트가 화면에 나타날 때 자동으로 포커스가 잡힙니다.
이제 검색어에 대한 상태를 관리해야합니다.
SearchHeade에서 입력한 검색으롤 SearchScreen에서 사용할 수 있어야합니다.
현재 SearchHeader 컴포넌트는 MainTab에서 사용하기 때문에 Context를 사용해야합니다.
contexts/SearchContext.js
import React, {createContext, useState} from 'react';
const SearchContext = createContext();
export function SearchContextProvider({children}) {
const [keyword, onChangeText] = useState('');
return (
<SearchContext.Provider value={{keyword, onChangeText}}>
{children}
</SearchContext.Provider>
);
}
export default SearchContext;
이번에는 별도로 만들 함수가 없습니다.
useState로 만든 상태값인 keyword와 업데이트 함수인 onChangeText를
SearchContext.Provider의 valuefh 설정하면 됩니다.
context를 다 만든 후 App 컴포넌트를 열어 사용합니다.
SearchContext와 기존에 만든 LogContext는 의존 관계가 아니기 때문에
Provider 컴포넌트의 사용 순서는 중요하지 않습니다
App.js
import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import RootStack from './screens/RootStack';
import {LogContextProvider} from './contexts/LogContext';
import {SearchContextProvider} from './contexts/SearchContext';
function App() {
return (
<NavigationContainer>
<SearchContextProvider>
<LogContextProvider>
<RootStack />
</LogContextProvider>
</SearchContextProvider>
</NavigationContainer>
);
}
export default App;
SearchHeader 에는 TextInput에 value와 onChangeText Props를 설정합니다.
그리고 우측에 Pressable을 눌렀을 때 텍스트가 초기화되도록 설정하겠습니다.
conponents/SearchHeader.js
import React, { useContext } from "react";
import {
View,
StyleSheet,
Text,
useWindowDimensions,
Pressable,
TextInput,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';//추가
import SearchContext from "../contexts/SearchContext";
function SearchHeader() {
const {width} = useWindowDimensions();
//추가
const { keyword, onChangeText } = useContext(SearchContext);
// ---
return (
<View style={[styles.block, {width: width - 32}]}>
<TextInput
style={styles.input}
placeholder={'검색어를 입력하세요'}
autoFocus
//추가
value={keyword}
onChangeText={onChangeText}
// -----
/>
<Pressable
style={({pressed}) => [styles.button, pressed && {opacity: 0.5}]}
onPress={()=> onChangeText('')} //추가
>
(...)
SearchScreen에는 임시로 Text를 사용해 검색어를 화면에 보여주도록 설정합시다.
SearchContex가 잘 작동하고 있는지 검증하기 위해서 입니다.
screens/SearchScreen.js
import React, {useContext} from 'react';
import {View, StyleSheet, Text} from 'react-native';
import SearchContext from '../contexts/SearchContext';
function SearchScreen({navigation}) {
const {keyword} = useContext(SearchContext);
return (
<View style={styles.block}>
<Text>{keyword}</Text>
</View>
);
}
const styles = StyleSheet.create({
block: {},
});
export default SearchScreen;
이제 SearchKeyword에 검색어가 나타 날 것입니다.
검색어 필터링 후 FeedList 재사용하기
이제 검색기능을 구현해보겠습니다.
배열의 내장 함수 filter 함수를 통해 구현하면 됩니다.
screens/SearchSecreen.js
import React, {useContext} from 'react';
import {View, StyleSheet, Text} from 'react-native';
import SearchContext from '../contexts/SearchContext';
import LogContext from '../contexts/LogContext';
import FeedList from "../components/FeedList";
function SearchScreen({navigation}) {
const {keyword} = useContext(SearchContext);
//추가
const {logs} = useContext(LogContext);
const filtered =
keyword === ''
? []
: logs.filter(log =>
[log.title, log.body].some(text => text.includes(keyword)),
);
//-------
return (
<View style={styles.block}>
<FeedList logs={filtered} /> //수정
</View>
);
}
const styles = StyleSheet.create({
block: {
flex : 1 //추가
},
});
export default SearchScreen;
text.includes라는 문자열 내장 함수를 사용했습니다.
이는 텍스트에 특정 문자열이 존재하는지 확인하는 함수입니다.
만약 존재한다면 true를 반환하고 그렇지 않으면 false를 반환합니다.
[log.title, log.body] 배열에서 사용한 some라는 배열 내장함수는
배열 원소 중 특정 조건이 true인 원소가 하나로도 있으면 true를 반환하고
모든 원소가 특정 조건을 만족하지 않을시 false를 반환합니다.
이제 검색 결과가 나오는지 확인해보겠습니다.
EmptySearchResult 만들기
이제 검색기능은 다 구현했고 검색결과가 없을 때 안내문구를 보여주는 컴포넌트를 만들겠습니다.
검색결과가 없는 상황은 두가지로
첫째는 사용자가 검색어를 입력하지 않았을 때이고,
두번째는 검색어와 일치하는 결과물이 없을 때 입니다.
components/EmptySearchResult.js
import React from 'react';
import {View, StyleSheet, Text} from 'react-native';
const messages = {
NOT_FOUND: '검색 결과가 없습니다.',
EMPTY_KEYWORD: '검색어를 입력하세요.',
};
function EmptySearchReault({type}) {
return (
<View style={styles.block}>
<Text style={styles.text}>{messages[type]}</Text>
</View>
);
}
const styles = StyleSheet.create({
block: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
text: {
color: '#9e9e9e',
fontSize: 16,
},
});
export default EmptySearchReault;
이 컴포넌트는 type라는 Props를 받아옵니다.
이제 이 컴포넌트를 SearchScreen에 사용하겠습니다.
screens/SearchScreen.js
import React, {useContext} from 'react';
import {View, StyleSheet, Text} from 'react-native';
import SearchContext from '../contexts/SearchContext';
import LogContext from '../contexts/LogContext';
import FeedList from '../components/FeedList';
import EmptySearchReault from "../components/EmptySearchResult";
function SearchScreen({navigation}) {
const {keyword} = useContext(SearchContext);
const {logs} = useContext(LogContext);
const filtered =
keyword === ''
? []
: logs.filter(log =>
[log.title, log.body].some(text => text.includes(keyword)),
);
//추가
if (keyword ===''){
return <EmptySearchReault type={'EMPTY_KEYWORD'} />
}
if (filtered.length === 0){
return <EmptySearchReault type={'NOT_FOUND'} />
}
//---
return (
<View style={styles.block}>
<FeedList logs={filtered} />
</View>
);
}
const styles = StyleSheet.create({
block: {
flex: 1,
},
});
export default SearchScreen;
'코딩생활 > ReactNative' 카테고리의 다른 글
[React Native] 3-12 달력 기능 구현하기 (2) (0) | 2023.04.03 |
---|---|
[React Native] 3-12 달력 기능 구현하기 (1) (0) | 2023.03.31 |
[React Native] 3-11 검색 기능 구현하기 (1) (0) | 2023.03.27 |
[React Native] 3-10 삭제 기능 구현하기 (0) | 2023.03.26 |
[React Native] 3-9 작성한 글을 WriteScreen으로 열기 (0) | 2023.03.20 |
댓글