Instantly share code, notes, and snippets.

Embed
What would you like to do?
Search Bar with a ListView using an API
import React, {Component} from 'react'
import {
Text,
StyleSheet,
View,
ListView,
TouchableHighlight,
Dimensions,
Image,
Animated,
TextInput
} from 'react-native'
import dataJson from '../data.json'
import Navbar from './Navbar'
const {width, height} = Dimensions.get('window')
export default class App extends Component {
constructor(props){
super(props)
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2})
this.state = {
isLoaded: false,
isOpenMenu: false,
dataSource: ds.cloneWithRows([]),
rawData: '',
empty: true,
isLoading: false,
rotateY: new Animated.Value(0),
translateX: new Animated.Value(width),
menuAnimation: new Animated.Value(0),
text: ''
}
}
componentWillMount() {
this.fetchData()
}
fetchData(){
fetch('https://api.tvmaze.com/schedule')
.then((res) => res.json())
.then((data) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(data),
isLoading: false,
empty: false,
rawData: data
})
})
.catch((error) => {
this.setState({
empty: true,
})
})
}
showMenu(){
if(this.state.isOpenMenu){
this.setState({isOpenMenu: false})
Animated.parallel([
Animated.timing(
this.state.translateX, {
toValue: width
}
),
Animated.timing(
this.state.rotateY, {
toValue: 0
}
)
]).start()
} else {
this.setState({isOpenMenu: true})
Animated.parallel([
Animated.timing(
this.state.translateX, {
toValue: width * 0.60
}
),
Animated.timing(
this.state.rotateY, {
toValue: 1
}
),
Animated.timing(
this.state.menuAnimation, {
toValue: 1,
duration: 800
}
)
]).start()
}
}
closeMenu(){
this.setState({isOpenMenu: false})
Animated.parallel([
Animated.timing(
this.state.translateX, {
toValue: width
}
),
Animated.timing(
this.state.rotateY, {
toValue: 0
}
),
Animated.timing(
this.state.menuAnimation, {
toValue: 0,
duration: 300
}
)
]).start()
}
renderRow(rowData){
return (
<TouchableHighlight style={styles.containerCell}
>
<View>
<View style={styles.footerContainer}>
<View style={styles.footerTextContainer}>
<Text style={styles.text}>{rowData.name}</Text>
<Text style={[styles.text, styles.textTitle]}>{rowData.number}</Text>
<Text style={[styles.text, styles.textBy]}>By {rowData.airdate}</Text>
</View>
</View>
</View>
</TouchableHighlight>
)
}
filterSearch(text){
this.setState({text})
let newData = this.dataFilter(text, this.state.rawData);
this.setState({
dataSource: this.state.dataSource.cloneWithRows(newData),
isLoaded: true,
empty: false
})
}
dataFilter(text, data){
return data.filter(function(item){
const itemData = item.name.toUpperCase()
const textData = text.toUpperCase()
return itemData.indexOf(textData) > -1
})
}
render(){
return (
<View style={styles.container}>
<Animated.View
style={[styles.content, {
width: width,
backgroundColor: 'gray',
flex: 1,
transform: [
{
perspective: 450
},
{
translateX: this.state.translateX.interpolate({
inputRange: [0, width],
outputRange: [width, 0]
})
},
{
rotateY: this.state.rotateY.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '-10deg']
})
}
]
}]}
>
{this.state.isOpenMenu ? <Navbar icon="times" showMenu={this.closeMenu.bind(this)}/> : <Navbar icon="bars" showMenu={this.showMenu.bind(this)}/>}
<TextInput
style={styles.textInput}
onChangeText={(text) => this.filterSearch(text)}
value={this.state.text}
/>
<ListView
enableEmptySections={true}
style={styles.listContainer}
renderRow={this.renderRow.bind(this)}
dataSource={this.state.dataSource}
/>
</Animated.View>
<Animated.View
style={[styles.menu, {
opacity: this.state.menuAnimation,
position: 'absolute',
width: 140,
left: 0,
top: 100,
backgroundColor: 'transparent'
}]}
>
<Text style={styles.textMenu}>Home</Text>
<Text style={styles.textMenu}>New Recipes</Text>
<Text style={styles.textMenu}>Recipes</Text>
<Text style={styles.textMenu}>Profile</Text>
<Text style={styles.textMenu}>Settings</Text>
</Animated.View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#555566'
},
textInput: {
height: 30,
borderWidth: 1,
borderColor: '#cecece',
marginBottom: 10,
marginHorizontal: 10
},
content: {
zIndex: 1
},
footerContainer: {
flexDirection: 'row',
paddingHorizontal: 10,
paddingVertical: 10,
backgroundColor: '#555566'
},
imageAvatar: {
width: 50,
height: 50,
borderRadius: 25,
marginRight: 5
},
listContainer: {
marginHorizontal: 10
},
text: {
color: '#fff'
},
containerCell: {
marginBottom: 10
},
textTitle: {
fontSize: 13
},
textBy: {
fontSize: 12
},
textMenu: {
fontSize: 20,
color: '#fff'
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment