There are two screens addcity and cities. I am sending data from addcity via props and receiving in cities properly and I am trying to iterate data from props via map function but it is not printing data on my device, in fact, I have checked in the console and it is showing data correctly but not in View.
I am using react-naviagtion library with bottomtabnavigator and sending props with navigation props.
app.js
state = {
cities: []
}
addCity = city => {
const cities = this.state.cities;
cities.push(city);
this.setState({ cities })
}
render() {
return (
<Tabs screenProps={{ cities: this.state.cities, addCity: this.addCity }} />
)
}
cities component
render() {
return (
<View>
{
this.props.screenProps.cities.map((city, index) => {
console.log(city);
<Text style={{ color: 'black' }}>{city.city}</Text>
})
}
</View>
)
}
}
addcity component
onSubmit = () => {
if (this.state.city === '' || this.state.country === '') return
const city = {
id: uuidV4(),
city: this.state.city,
country: this.state.country,
locations: []
}
this.props.screenProps.addCity(city);
this.setState({
city: '',
country: ''
}, () => { this.props.navigation.navigate('Cities') });
}
render() {
console.log('props', this.props);
return (
<View style={styles.container}>
<Text style={styles.heading}>Cities App</Text>
<TextInput style={styles.input} placeholder='City' value={this.state.city} onChangeText={val => this.onChangeTextInput('city', val)} />
<TextInput style={styles.input} placeholder='Country' value={this.state.country} onChangeText={val => this.onChangeTextInput('country', val)} />
<TouchableOpacity onPress={this.onSubmit}>
<View style={styles.button}>
<Text style={styles.buttonText}> Add City </Text>
</View>
</TouchableOpacity>
</View>
)
}
}
I am expecting to be city name in Text Component but it showing empty, even though I checked the console and it's consoling my data properly
modify cities component like this:
render() {
return (
<View>
{
this.props.screenProps.cities.map((city, index) => {
console.log(city);
return (
<Text style={{ color: 'black' }}>{city.city}</Text>
)
})
}
</View>
)
}
}
Your map function should construct the text element and return it, you're not returning it.
Related
I am trying to send the data of the flatlist items when clicked and set to another class.The ontouch is working but I am having the error below in the image. Also how can I send the data of api to the other class and get from another class? I have implemented as follows:
export default class FlatSpeakers extends Component {
constructor(props) {
super(props);
this.state = { isLoading: true, data: [],selectedItem: null, }
const { navigate } = this.props.navigation;
}
onPressItem = () => {
navigate('SpeakersClick')
};
componentDidMount() {
axios.get('https://rallycoding.herokuapp.com/api/music_albums')
.then(res => {
this.setState({
isLoading: false,
data: res.data,
})
})
}
renderItem({ item }) {
return (
<TouchableOpacity onPress={()=>this.onPressItem(item)} >
<Card>
<CardSection>
<View style={styles.thumbnailContainerStyle}>
<Image
style={styles.thumbnailStyle}
source={{ uri: item.image }}
/>
</View>
<View style={styles.headerContentStyle}>
<Text style={styles.headerTextStyle}>{item.title}</Text>
<Text>{item.artist}</Text>
</View>
</CardSection>
</Card>
</TouchableOpacity>
)
}
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, padding: 20 }}>
<ActivityIndicator />
</View>
)
}
return (
<View style={styles.container}>
<FlatList
data={this.state.data}
renderItem={this.renderItem}
keyExtractor={(item, index) => index}
onPress={this.onPressItem}
/>
</View>
);
}
}
Problem in your code is, that you are calling same method from two sides - on one side you are passing arguments in it on another side you are not passing arguments. If you wan't to have both cases covered you should change you onPressFunction, to accept arguments - in your case item:
onPressItem = (item) => {
navigate('SpeakersClick')
};
try to put this.onPressItem = this.onPressItem.bind(this) on constructor(props)
I got a chat based on react-native-gifted-chat, with a children InputBox component that has the layout for the input and some buttons plus the Send button.
I'm passing 2 functions to handle onSend and the camera, but I was wondering how to send the text that I'm writing on the InputBox to parent that contains the GiftedChat.
GiftedChat handles an array of messages, but how do I create a new text message based on the input and the button onPress ?
Here's my current code:
On Parent
constructor(props) {
super(props)
this.handleCameraPress = this.handleCameraPress.bind(this);
this.onSend = this.onSend.bind(this);
this.state = {
chatData: {},
messages: []
}
}
onSend(messages = []) {
alert('sending message');
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, messages),
}))
}
handleCameraPress() {
alert('camera tapped');
}
renderInputToolbar(props) {
return ( <InputBox
{...props}
messages={ this.messages }
onSend={ this.onSend }
handleCameraPress={ this.handleCameraPress }
containerStyle={ styles.inputToolbarStyle }
/>);
}
This is how the GiftedChat looks like:
<GiftedChat
style={{ zIndex: 1 }}
messages={this.state.messages}
bottomOffset={Platform.OS === "ios" ? 335 : 0}
maxComposerHeight={150}
isAnimated={true}
user={{ _id: 1 }}
renderInputToolbar={ this.renderInputToolbar.bind(this) }
/>
On Children
render() {
return (
<View style={ styles.container }>
<TouchableOpacity
activeOpacity={0.6}
style={styles.cameraButton}
onPress={ this.props.handleCameraPress }>
<Icon name='md-camera' style={ styles.cameraIcon } />
</TouchableOpacity>
<TextInput
style={ styles.textInput }
placeholder={i18n.t('chatInputPlaceholder')}
returnKeyType={'send'}
// onChangeText={ message => this.setState({ message })}
// value={this.props.message}
blurOnSubmit={false}
ref={'chatInputRef'}
/>
<Button
onPress={ this.props.onSend }
style={ styles.sendButton}>
<Icon name='md-send' style={ styles.sendIcon } />
</Button>
</View>
);
}
I have to I guess pass a this.props.message to this.props.onSend? And then merge it to parent's messages?
You have to create a state variable , which will be your current Message , and then in Gifted chat , you implement :
onInputTextChanged={text => {this.setState({typingMessage: text});}}
So now your "this.state.typingMessage" , will always have the value that you are writing in your InputToolbar
If you have a custom render you can access to Input Toolbar value like this with "props.text" :
renderSend(props) {
return (
<TouchableOpacity onPress={() => props.onSend({
_id: 10,
text: props.text,
createdAt: new Date(),
user: {
_id: 1,
name: 'Mike',
},
})}>
</TouchableOpacity>
);
}
I am trying to make a search in my db items but all I receive is the following error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Here is my code where I am creating the search page. JobItem I am using it in jobs page and everything is displaying correctly but here when I put the first letter in the search box I am getting the error.
import JobItem from './JobItem';
const { width, height } = Dimensions.get('window')
class SearchBar extends Component {
constructor(props) {
super(props)
this.state = {
text: '',
data: ''
}
}
static navigationOptions = {
headerVisible: false
}
filter(text) {
const data = this.props.jobs;
console.log(data);
const newData = data.filter(function (job) {
const itemData = job.title.toUpperCase()
const textData = text.toUpperCase()
return itemData.indexOf(textData) > -1
})
this.setState({
data: newData,
text: text,
})
}
deleteData() {
this.setState({ text: '', data: '' })
}
_renderJobs(job) {
return this.props.jobs.map((job) => {
return (
<JobItem
key={job._id}
title={job.title}
shortDescription={job.shortDescription}
logo={job.avatar}
company={job.company}
id={job._id}
city={job.location[0].city}
postDate={job.postDate}
dispatch={this.props.dispatch}
onPress={() => this.onJobDetails(job)}
/>
)
})
}
render() {
const { goBack } = this.props.navigation
return (
<View style={styles.container}>
<View style={styles.header}>
<FontAwesome
name="magnify"
color="grey"
size={20}
style={styles.searchIcon}
/>
<TextInput
value={this.state.text}
onChangeText={(text) => this.filter(text)}
style={styles.input}
placeholder="Search"
placeholderTextColor="grey"
keyboardAppearance="dark"
autoFocus={true}
/>
{this.state.text ?
<TouchableWithoutFeedback onPress={() => this.deleteData()}>
<FontAwesome
name="clock-outline"
color="grey"
size={20}
style={styles.iconInputClose}
/>
</TouchableWithoutFeedback>
: null}
<TouchableWithoutFeedback style={styles.cancelButton} onPress={() => goBack()}>
<View style={styles.containerButton}>
<Text style={styles.cancelButtonText}>Cancel</Text>
</View>
</TouchableWithoutFeedback>
</View>
<ScrollView>
<FlatList
style={{ marginHorizontal: 5 }}
data={this.state.data}
numColumns={3}
columnWrapperStyle={{ marginTop: 5, marginLeft: 5 }}
renderItem={({ job }) => this._renderJobs(job)}
/>
</ScrollView>
</View>
)
}
}
Please anyone help me with this.
I have code
AsyncStorage.getItem("Friends").then((value) => {
this.setState({"Friends": value});
}).done();
I am trying to show in list using
render() {
return ({
this.state.Friends.map((o,i) => {
<View key={i} style={styles.row}>
<View>
<Text style={styles.app_type_name}>{o.name}</Text>
</View>
</View>
})
})
}
I am getting
error evaluating object 'this.state.Friends'
You render method should looks like :
render() {
const {Friends} = this.state;
return (
<div>
{
Friends && Friends.map((o,i) =>
<View key={i} style={styles.row}>
<View><Text style={styles.app_type_name}>{o.name}</Text></View>
</View>
)
}
</div>
);
}
I'm new in ReactNative. I'm following a tutorial from Udemy. I've been trying to show a value from a variable. its working in the instructor's video but not in my code. the code is given below:
export default class App extends React.Component {
state = {
placeName: '',
places: []
}
placeNameChangedHandler = val => {
this.setState({
placeName: val
})
}
placeSubmitHandler = () => {
if (this.state.placeName.trim() === "") {
return;
}
this.setState(prevState => {
return {
places: prevState.places.concat(prevState.placeName)
}
})
}
render() {
const placesOutput = this.state.places.map(place => {
<Text>{place}</Text>
})
return (
<View style={styles.container}>
<View style={styles.inputContainer}>
<TextInput
placeholder="Type something"
style={styles.placeInput}
value={this.state.placeName}
onChangeText={this.placeNameChangedHandler}/>
<Button
style={styles.placeButton}
onPress={this.placeSubmitHandler}
title="Add"/>
</View>
<View>
{this.placesOutput}
</View>
</View>
);
}
}
but the {placeOutput} is not showing anything. its working in the instructor's video but not in my code. What am I doing wrong?
You aren't returning anything in your map() function. Your render function should look like this:
render() {
const placesOutput = this.state.places.map(place => {
return <Text>{place}</Text> //Added return statement
})
return (
<View style={styles.container}>
<View style={styles.inputContainer}>
<TextInput
placeholder="Type something"
style={styles.placeInput}
value={this.state.placeName}
onChangeText={this.placeNameChangedHandler}/>
<Button
style={styles.placeButton}
onPress={this.placeSubmitHandler}
title="Add"/>
</View>
<View>
{this.placesOutput}
</View>
</View>
);
}
All I did was add a return statement in your this.state.places.map() function.