I'm new at react native.I have a problem that i've been dealing for a few days.I want to show my data with map.Can you guys show me where i did wrong?
(I think i made mistake in the results inside scrollview)
class Movie extends Component{
state= {
apiurl:'http://www.omdbapi.com/.............................',
s:'',
results: [],
selected:{}
}
searchFunc(s) {
this.setState({s: s})
axios(this.state.apiurl+ "&s="+s).then(response =>
this.setState({results: response.data.Search[0]}));
console.log(this.state.results)
}
render() {
return(
<View style={{flex:1,backgroundColor:'#356292'}}>
<View
style={styles.sectionContainer}>
<View style={styles.section}>
<TextInput style={styles.section2}
onChangeText = {(s) => this.searchFunc({s})}
value={this.state.s}
placeholder="Movies,Series.."
>
</TextInput>
<TouchableOpacity
style={{justifyContent: 'center', alignItems: 'center'}}
onPress={() => this.searchFunc()}>
<Image
source ={require('../img/seach.png')}
style={{width:width*0.05,height:height*0.03}}
>
</Image>
</TouchableOpacity>
</View>
</View>
<ScrollView style={styles.scroll}>
{this.state.results.map(results=>(
<View key={this.state.results.imdbID}
style={styles.scroll2}>
<Image source={{uri: this.state.results}}
style={{width:width*0.3, height:height*0.4}}>
</Image>
<Text style={styles.heading}>
{this.state.results.Title}
</Text>
</View>
))}
</ScrollView>
</View>
);
}
From the comments from your original post, i'm guessing response.data.Search[0] is also an array. If so your results state update is okay. Otherwise you should set the results state to response.data.Search.
Other problem I noticed in your code is in the map function, you are mapping the array with each item refering to the result variable, but in your jsx, you are trying to access the results state variable. It should be
<ScrollView style={styles.scroll}>
{
this.state.results.map(result => (
<View
key={result.imdbID}
style={styles.scroll2}
>
<Image
source={{uri: result.image}} // use correct key from result object
style={{width:width*0.3, height:height*0.4}}
/>
<Text style={styles.heading}>{result.Title}</Text>
</View>
))
}
</ScrollView>
Also in your Textinput onChangeText callback function, you dont have to pass that value as an object. You can change it to
<TextInput
style={styles.section2}
onChangeText={(s) => this.searchFunc(s)}
value={this.state.s}
placeholder="Movies,Series.."
/>
I quess you are supposed to pass Search to the state and not the Search[0], which is the object and not map, the reason map function is not working on it.
axios(this.state.apiurl+ "&s="+s).then(response =>
this.setState({results: response.data.Search}));
console.log(this.state.results)
Coincidently, I have created an app using same movie API, you can find it here: Github Repo, Movie App
Related
I want to copy value inside textview by clicking to icon. This is what I've done so far:
render() {
return (
<View style={{marginTop: 50, marginLeft: 50}}>
<View>
<Text>Логин:</Text>
<Text ref='myText'>45645546654</Text>
</View>
<TouchableOpacity onPress={() => Clipboard.setString(this.refs.myText.props.children)}>
<View>
<MaterialIcons
name='content-copy'
size={21}
/>
</View>
</TouchableOpacity>
</View>
);
}
Workspace: https://snack.expo.io/#jasurkurbanov/updated2
It is somewhat working on snack. But what when I am running it on my phone I am getting error.
Undefinied is not an object ('evaluating '_this.refs.myText.props.children')
You should defined your refs variable on constructor().
for example:
constructor() {
...
this.textViewRefs = React.createRef();
...
}
render() {
return (
...
<Text ref={this.textViewRefs}>45645546654</Text>
...
)
}
look this https://reactjs.org/docs/forwarding-refs.html for further information
I am trying to make cards clickable and expandable, but when updating state, it occurs in all the cards . I just want to make the state change in only one card (the one on which the event occurred , in this case, a click event).
However, the state gets updated for every other cards. Currently this does work on one item but it needs to work on others too.
export default class TransactionCards extends React.Component {
constructor(props) {
super(props);
this.state = {
isHidden: true
};
}
toggleHidden() {
this.setState({
isHidden: !this.state.isHidden
});
}
renderCards() {
return this.props.data.map((card, index) => (
<View key={card.id}>
<View style={styles.dateContainer}>
<Text style={styles.dateText}>{card.time}</Text>
</View>
<Card>
<TouchableWithoutFeedback onPress={this.toggleHidden.bind(this)}>
<View>
<View>
<View style={styles.transactionContainer}>
<Image
style={styles.countryImage}
source={require("../../assets/images/us-country-icon.png")}
/>
<Text style={styles.transactionTitle}>{card.title}</Text>
<Text style={styles.transactionAmount}>{card.cost}</Text>
<Icon
name={card.transactionType == "debit" ? "log-out" : "log-in"}
type="feather"
color={card.transactionType == "debit" ? "red" : "green"}
size={18}
iconStyle={styles.transactionIcon}
/>
</View>
<View>
<Text style={styles.transactionBankDetails}>{card.bankDetails}</Text>
</View>
</View>
{/* Setting visiblity condition */}
{!this.state.isHidden && (
<View>
<Divider style={styles.CardItemDivider} />
<View display="flex" flexDirection="row" justifyContent="space-between">
<View>
<Text style={styles.transactionBankDetails}>
{card.transactionCategory}
</Text>
<Text style={styles.transactionBankDetails}>{card.accountName}</Text>
</View>
<View>
<Icon name="bell" type="feather" iconStyle={styles.transactionIcon} />
</View>
</View>
</View>
)}
</View>
</TouchableWithoutFeedback>
</Card>
</View>
));
}
render() {
return <ScrollView showsVerticalScrollIndicator={false}>{this.renderCards()}</ScrollView>;
}
}
Create a new component for card and pass required params
Do the toggleHidden function inside the Card component
then inside the file it should look like
<Card {SetYourPassedParams} />
......
You have two items connected to the same state value on the same state. If you want to separate the behaviours you have to separate the values too.
I have a flat list, which gets its data source as a state. Actually, this data is from firebase, and i have been using redux. So, the data is fetched in the actions, and using callback i get the data to state.
What i want to achieve is, when there is no data found from the api, An empty list message should be show in the view. Actually , i achieved this using "ListEmptyComponent". But whats happening is the screen starts with empty message, and the spinner loads below it, and then if data found the message goes away as well as spinner.
But, what i wanted is, when the view gets rendered the first thing everyone should see is the spinner, and then if data empty spinner hides then empty list message displays.
How to achieve this ?
My Action :
export const fetchOrderHistory = (phone, callback) => {
return (dispatch) => {
dispatch({ type: START_SPINNER_ACTION_FOR_ORDER_HISTORY })
firebase.database().ref('orders/'+phone)
.on('value', snapshot => {
const snapShotValue = snapshot.val();
callback(snapShotValue);
dispatch ({ type: ORDER_HISTORY_FETCHED , payload: snapshot.val()});
dispatch({ type: STOP_SPINNER_ACTION_FRO_ORDER_HISTORY })
});
};
};
My Flat List & spinner:
<FlatList
data={this.state.historyOfOrders}
keyExtractor={item => item.uid}
ListEmptyComponent={this.onListEmpty()}
renderItem={({ item }) => (
<Card
containerStyle={{ borderRadius: 5 }}
>
<View style={styles.topContainerStyle}>
<View>
<TouchableOpacity
onPress={() => this.props.navigation.navigate('ViewOrderScreen', {itemsOfOrder: item}) }
>
<View style={styles.viewOrderContainer}>
<View style={styles.viewOrderTextContainer}>
<Text style={styles.viewOrderTextStyle}>View Order</Text>
</View>
<Icon
name='ios-arrow-forward'
type='ionicon'
color='#ff7675'
/>
</View>
</TouchableOpacity>
</View>
</View>
</View>
</Card>
)}
/>
{this.props.isSpinnerLoading &&
<View style={styles.loading}>
<ActivityIndicator size="large" color="#03A9F4"/>
</View> }
My Call back at componentWillMount which set state:
componentWillMount() {
this.props.fetchOrderHistory((this.props.phone), (snapShotValue)=> {
const userOrderHistory = _.map(snapShotValue, (val,uid) => ({uid, ...val}))
this.setState({ historyOfOrders: userOrderHistory })
});
}
My EmptyList Message:
onListEmpty = () => {
return <View style={{ alignSelf: 'center' }}>
<Text style={{ fontWeight: 'bold', fontSize: 25 }}>No Data</Text>
</View>
}
My State:
state = { historyOfOrders: "" }
I am getting the spinner values from the reducers, using mapStateToProps.
Kindly Guide me, through
you have to do two things for that.
First, show Flatlist only if the loader is stopped. Second, set default value of this.state.historyOfOrders is null and check if this.state.historyOfOrders not null then only show Flatlist.
Here is a code:
{(!this.props.isSpinnerLoading && this.state.historyOfOrders != null) ?
(
<FlatList
data={this.state.historyOfOrders}
keyExtractor={item => item.uid}
ListEmptyComponent={this.onListEmpty()}
renderItem={({ item }) => (
<Card containerStyle={{ borderRadius: 5 }}>
<View style={styles.topContainerStyle}>
<View>
<TouchableOpacity onPress={() => this.props.navigation.navigate('ViewOrderScreen', {itemsOfOrder: item}) }>
<View style={styles.viewOrderContainer}>
<View style={styles.viewOrderTextContainer}>
<Text style={styles.viewOrderTextStyle}>View Order</Text>
</View>
<Icon
name='ios-arrow-forward'
type='ionicon'
color='#ff7675'
/>
</View>
</TouchableOpacity>
</View>
</View>
</Card>
)}
/>
) : null
}
With this condition, even if you want loader above Flatlist you can do that.
The path you should take is rendering only the spinner when the loading flag is set and rendering the list when loading flag is false.
Your render method should be like below
render()
{
if(this.props.isSpinnerLoading)
{
return (<View style={styles.loading}>
<ActivityIndicator size="large" color="#03A9F4"/>
</View> );
}
return (/** Actual List code here **/);
}
I have this code:
<View style={{flex:1}}>
<ScrollView>
<View style={{flex:0.25,elevation:2,marginVertical:5}}>
<MoviesChild/>
</View>
<View style={{flex:0.75}}>
<FlatList
data={ListOfMovies}
renderItem={this.renderData.bind(this)}
keyExtractor={(x, i) => x.id}
extraData={this.state}
/>
</View>
</ScrollView>
</View>
The problem is, my FlatList's data appears but my child component MoviesChild disappears. Maybe Flatlist overlaps the child component. Could someone figure out where I'm doing a mistake please?
You should give style to ScrollView with flexGrow:1
I suggest you not to use FlatList inside a ScrollView, 'cause FlatList scroll itself. So, in order to achieve your objective, wrap your first View in a function and pass it to the ListHeaderComponent property of your FlatList, like this:
<View style={{flex:1}}>
<View style={{flex:0.75}}>
<FlatList
data={ListOfMovies}
renderItem={this.renderData.bind(this)}
keyExtractor={(x, i) => x.id}
extraData={this.state}
ListHeaderContainer={this.renderHeader}
/>
</View>
</View>
where
private renderHeader = () => {
return(
<View style={{flex:0.25,elevation:2,marginVertical:5}}>
<MoviesChild/>
</View>
)
}
I hope this can fix your issue!
You can find what I'm talking about on the official doc
Try this,
<View style={{flex:1}}>
<View style={{ flex:0.25,elevation:2,marginVertical:5 }}>
<MoviesChild/>
</View>
<FlatList
style={{flex:0.75}}
data={ListOfMovies}
renderItem={this.renderData.bind(this)}
keyExtractor={(x, i) => x.id}
extraData={this.state}
/>
</View>
Hello there i am working on a beginner project of mine with React Native and right now i am not able to handle onPress event.
Render:
_renderRow(feed) {
return (
<TouchableHighlight onPress={() => this._pressRow()}>
<View style={styles.container}>
<Image
source={{uri: feed.thumbnail}}
style={styles.thumbnail}/>
<View style={styles.rightContainer}>
<Text style={styles.title}>{feed.title}</Text>
</View>
</View>
</TouchableHighlight>
);
}
And the onPress function
_pressRow() {
console.log('list item pressed')
}
Listview
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderRow}
style={styles.listView}/>
This is what i get as an error.
undefined is not a function (evaluating _this3._pressRow())
EDIT
Thanks to #Cherniv. I forgot to bind this with the renderRow function, changed my code like that and worked as intended:
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderRow.bind(this)}
style={styles.listView}/>
Is it not because you forgot the "_" before pressRow in method declaration ?