ListItem not rendering data in React native - react-native

hi im trying to render some user info in my react native page and i dont know why it should render something like this:
list
but instead my output is
list
so my FlatList is working but my ListItem is no rendering any data someone could help me?
i dont know if it is a bug with reactnativeelements or so
User data
export default [
{
id: 1,
name: 'Tiago Almeida',
email: 'tiago#gmail.pt',
avatarUrl:
'https://cdn.pixabay.com/photo/2013/07/13/10/07/man-156584_960_720.png',
},
{
id: 2,
name: 'Lucas Silva',
email: 'lucas#gmail.com',
avatarUrl:
'https://cdn.pixabay.com/photo/2014/04/03/10/32/businessman-310819_960_720.png',
},
{
id: 3,
name: 'Andre Ferreira',
email: 'andre#gmail.pt',
avatarUrl:
'https://cdn.pixabay.com/photo/2018/05/19/22/03/man-3414477_960_720.png',
},];
and this is my main page
export default props => {
function getActions(user) {
return (
<>
<Button
onPress={() => props.navigation.navigate('UserForm', user)}
type='clear'
icon={<Icon name='edit' size={25} color='orange' />}
/>
</>
)
}
function getUserItem({ item: user }) {
return (
<ListItem
leftAvatar={{ source: { uri: user.avatarUrl } }}
key={user.id}
tittle={user.name}
subtitle={user.email}
bottomDivider
rightElement={getActions(user)}
onPress={() => props.navigation.navigate('UserForm', user)}
/>
)
}
return (
<View>
<FlatList
keyExtractor={user => user.id.toString()}
data={users}
renderItem={getUserItem}
/>
</View>
)
};

At the top in your imports write,
import { ListItem, Avatar } from 'react-native-elements';
After that Change your code to this
You don't need getActions
Instead write like this,
const getUserItem = ({ item: user }) => (
<ListItem
bottomDivider
onPress={() => props.navigation.navigate('UserForm', user)}>
<Avatar source={{ uri: user.avatarUrl }} />
<ListItem.Content>
<ListItem.Title>{user.name}</ListItem.Title>
<ListItem.Subtitle>{user.email}</ListItem.Subtitle>
</ListItem.Content>
<ListItem.Chevron
name="edit"
size={25}
color="orange"
onPress={() => props.navigation.navigate('UserForm', user)}
/>
</ListItem>
);
return (
<View>
<FlatList
keyExtractor={(user) => user.id.toString()}
data={users}
renderItem={getUserItem}
/>
</View>
);
Working Example here

Related

How to prevent state reset while navigating between screens? react native

In react native app, I have a home screen and a second screen that the user uses to add items that should be displayed on the home screen. The problem is when I add items in the second screen and go to the home screen I can see the added items but when I go again to the second screen to add other items, it deletes the previously added items.
Any help to explain why this happens and how to handle it?
Thanks in advance
Here's the code of the app.
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="AddItem" component={AddItem} />
</Stack.Navigator>
</NavigationContainer>
);
}
and here's the home screen component
class Home extends Component {
render() {
const { expenseList } = this.props.route.params || '';
return (
<View style={styles.container}>
<Text style={styles.text}>Budget:</Text>
<Button
title="+"
onPress={() => this.props.navigation.navigate('AddItem')}
/>
<View>
{expenseList === '' && (
<TouchableOpacity
onPress={() => this.props.navigation.navigate('AddItem')}>
<Text>Create your first entry</Text>
</TouchableOpacity>
)}
{expenseList !== '' && (
<FlatList
style={styles.listContainer}
data={expenseList}
renderItem={(data) => <Text> title={data.item.name} </Text>}
/>
)}
</View>
</View>
);
}
}
and the second screen
class AddItem extends Component {
state = {
name: '',
amount: '',
expenseList: [],
};
submitExpense = (name, amount) => {
this.setState({
expenseList: [
...this.state.expenseList,
{
key: Math.random(),
name: name,
amount: amount,
},
],
});
};
deleteExpense = (key) => {
this.setState({
expenseList: [
...this.state.expenseList.filter((item) => item.key !== key),
],
});
};
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.input}
onChangeText={(name) => this.setState({ name })}
value={this.state.name}
placeholder="Name"
keyboardType="default"
/>
{this.state.name === '' && (
<Text style={{ color: 'red', fontSize: 12, paddingLeft: 12 }}>
Name is required
</Text>
)}
<TextInput
style={styles.input}
onChangeText={(amount) => this.setState({ amount })}
value={this.state.amount}
placeholder="Amount"
keyboardType="numeric"
/>
{this.state.amount === '' && (
<Text style={{ color: 'red', fontSize: 12, paddingLeft: 12 }}>
Amount is required
</Text>
)}
<Button
title="Add"
style={styles.btn}
onPress={() => {
if (
this.state.name.trim() === '' ||
this.state.amount.trim() === ''
) {
alert('Please Enter the required values.');
} else {
this.submitExpense(
this.state.name,
this.state.amount
);
}
}}
/>
<Button
title="Go to Dashboard"
style={styles.btn}
onPress = {() => { this.props.navigation.navigate("Home", {
expenseList: this.state.expenseList,
});}}
/>
<FlatList
style={styles.listContainer}
data={this.state.expenseList}
renderItem={(data) => <Text> title={data.item.name} </Text>}
/>
</View>
);
}
}
You have a few options:
1- Use Redux:
https://react-redux.js.org/using-react-redux/connect-mapstate
2- Save your state in the AsyncStorage and get it wherever you want
3- Pass your state as param in the route:
navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});

How to use the modal in the list in react native (a specific Modal for each list item)?

I made a customized list component (in React Native) which shows touchable images with some description texts.
I need each images open a specific Modal; but I don't know how!! where & how I should code the Modal??
... here is my photo list component:
export class CustomGallery extends Component {
render() {
let {list} = this.props;
return (
<View style={styles.container}>
<FlatList
numColumns={4}
data={list}
renderItem={({ item}) => (
<View style={styles.views}>
<TouchableOpacity style={styles.touch} >
<ImageBackground
style={styles.img}
source={{ uri: item.photo }}
>
<Text style={styles.txt}>{item.name}</Text>
<Text style={styles.txt}>{item.key}</Text>
<Text style={styles.txt}>{item.describtion}</Text>
</ImageBackground>
</TouchableOpacity>
</View>
)}
/>
</View>
);
}
}
For Modal you can use modal from material-ui - https://material-ui.com/components/modal/
The Modal component renders its children node infront of a backdrop component. Simple and basic example would be like a confirmation message that pops up asking whether you surely want to delete particular information or not.
From your code I am guessing you want to display information regarding the image using modal when you click on the image.
Here I have added Modal component:
import React from 'react';
import Modal from '#material-ui/core/Modal';
export class CustomGallery extends Component {
constructor() {
super();
this.state = {
modalOpen: false,
snackOpen: false,
modalDeleteOpen: false,
};
}
handleModalOpen = () => {
this.setState({ modalOpen: true });
}
handleModalClose = () => {
this.setState({ modalOpen: false });
}
render() {
let {list} = this.props;
return (
<View style={styles.container}>
<FlatList
numColumns={4}
data={list}
renderItem={({ item}) => (
<View style={styles.views}>
<TouchableOpacity style={styles.touch} >
<ImageBackground
style={styles.img}
onClick={() => this.handleModalOpen()}
>
{ item.photo }
</ImageBackground>
<Modal
open={this.state.modalOpen}
onClose={this.handleModalClose}
closeAfterTransition
>
<Text style={styles.txt}>{item.name}</Text>
<Text style={styles.txt}>{item.key}</Text>
<Text style={styles.txt}>{item.describtion}</Text>
</Modal>
</TouchableOpacity>
</View>
)}
/>
</View>
);
}
}
I am not sure about how you set the image. But anyways below method is an example of opening modal with dynamic data.
import React, {useState} from "react";
import { Button, TouchableOpacity, FlatList, Modal, Text } from "react-native";
function App() {
const [value, setValue] = useState("");
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
return (
<>
<FlatList
data={DATA}
renderItem={({item}) => (
<TouchableOpacity onPress={() => setValue(item.title)}>
<Text>{item.title}</Text>
</TouchableOpacity>
)}
/>
<Modal visible={value}>
<Text>{value}</Text>
<Button title="close" onPress={() => setValue("")} />
</Modal>
</>
)
}
export default App;

React Native listIem passed props

I have a question about how to pass props for one screen to another, and display the props using listItem from "React Native Elements".
First i will paste the code of the screen with the "Add Friend" form:
const addFriend = ({ navigation }) => {
const [friend, setFriend] = useState('');
const [phone, setPhone] = useState('');
return (
<View style={styles.container}>
<Input
placeholder='Friend Name'
onChangeText={friend => setFriend(friend)}
leftIcon={
<Icon
name='user'
size={24}
color='grey'
/>
}
/>
<Input
onChangeText={phone => setPhone(phone)}
placeholder='Friend Phone Number'
leftIcon={
<Icon
name='phone'
size={24}
color='grey'
/>
}
/>
<Button
title="Add Friend"
onPress={() => {
navigation.navigate('FriendList', { friend, phone })
}}
/>
</View>
);
}
Second, i will paste the screen that is suppose to show the list of friends i want to add, here i cant find the way to pass the props from the screen above, to the list:
const list = [
{
name: '',
avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/ladylexy/128.jpg',
subtitle: ''
}
]
const FriendList = ({ route, navigation }) => {
const { friend } = route.params;
const { phone } = route.params;
return (
<View style={styles.container}>
list.map((l, i) => (
<ListItem
key={i}
leftAvatar={{ source: { uri: l.avatar_url } }}
title={l.name}
subtitle={l.subtitle}
bottomDivider
/>
))
}
{/* <Text>{JSON.stringify(friend)} {JSON.stringify(phone)}</Text> */}
</View>
);
}
You can find your parameters that you pass to your second screen in
let {friend, phone} = this.props.navigation.state.params;

Not showing data fetched from api ( React Native )

I wanted to show a list of data fetched from API inside DropdownModal (https://github.com/sohobloo/react-native-modal-dropdown) . The data is user address consists of name , state , country and all related to address . But it won't show inside the dropdown and it shows loading icon which means it is null or undefined . But i did have the data fetched from the API which i verify by making alert to error and result ( yup both giving the same data which is the address ) .
Below are my code .
const {getAddresses} = auth;
var {width, height} = Dimensions.get('window');
class RegisterEventOne extends React.Component {
constructor(props) {
super(props);
this.state = {
event_id: '',
tshirt_size: '',
size: '',
address: '',
addressx: '',
};
this.onResult = this.onResult.bind(this);
this.onError = this.onError.bind(this);
}
handleWithDropdownCategory = id => {
this.setState({event_id: id});
};
handleWithDropdownSize = size => {
this.setState({tshirt_size: size});
};
TShirtSize = size => {
this.setState({size: size});
};
setAddress = address => {
this.setState({addressx: address})
}
componentDidMount() {
this.props.getAddresses(this.props.event.id, this.onResult, this.onError);
}
onError(error) {
alert(JSON.stringify(error));
}
onResult(result) {
this.setState({
address: result,
});
}
render() {
return (
<React.Fragment>
<StatusBar backgroundColor="black" barStyle="light-content" />
<SafeAreaView style={styles.container}>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={styles.scrollView}>
<View>
<Text style={styles.eventname}>{this.props.event.name}</Text>
<ModalDropdown
dropdownStyle={styles.dropdown}
dropdownTextStyle={{fontSize:15}}
style={styles.dropdown}
onSelect={(index, value) => {
this.handleWithDropdownCategory(value);
}}
options={this.props.event.categories.map(function(event) {
return event.name;
})}>
<View style={styles.dropdowncontainer}>
<Text>{this.state.event_id === '' ? 'Select Category' : this.state.event_id}</Text>
<Ionicons name="ios-arrow-down" size={20} color="black" />
</View>
</ModalDropdown>
<ModalDropdown
dropdownStyle={styles.dropdown}
dropdownTextStyle={{fontSize:15}}
style={styles.dropdown}
onSelect={(index, value) => {
this.handleWithDropdownSize(value);
this.TShirtSize(index+1);
}}
options={this.props.event.tshirts.map(function(event, index) {
return event.size;
})}
>
<View style={styles.dropdowncontainer}>
<Text>{this.state.tshirt_size === '' ? 'Select Tshirt Size' : this.state.tshirt_size}</Text>
<Ionicons name="ios-arrow-down" size={20} color="black" />
</View>
</ModalDropdown>
<ModalDropdown
dropdownStyle={styles.dropdown}
style={styles.dropdown}
dropdownTextStyle={{fontSize:15}}
onSelect={(index, value) => {
this.setAddress(value);
}}
options={this.state.address !== '' ? this.state.address.map(function(address, index) {
return address.id;
}):null}
>
<View style={styles.dropdowncontainer}>
<Text>{this.state.addressx === '' ? 'Select Address' : this.state.addressx}</Text>
<Ionicons name="ios-arrow-down" size={20} color="black" />
</View>
</ModalDropdown>
{/* <Text style={styles.header}>Compete with ohters (Optional)</Text>
<TextInput
style={styles.header}
onChangeText={text => onChangeText(text)}
placeholder="Set Date & Time (Time zone)"
/> */}
{/* <View style={styles.checkboxcontainer}>
<BouncyCheckbox
textColor="#000"
fillColor="orange"
fontFamily="JosefinSans-Regular"
text="Individual Competition"
/>
<BouncyCheckbox
textColor="#000"
fillColor="orange"
fontFamily="JosefinSans-Regular"
text="Team Competition"
/>
<TextInput
style={styles.header}
onChangeText={text => onChangeText(text)}
placeholder="Team member limit"
/>
<TextInput
style={styles.header}
onChangeText={text => onChangeText(text)}
placeholder="Username / Email"
/>
<TextInput
style={styles.header}
onChangeText={text => onChangeText(text)}
placeholder="Username / Email"
/>
<TextInput
style={styles.header}
onChangeText={text => onChangeText(text)}
placeholder="Username / Email"
/>
</View> */}
</View>
</ScrollView>
<View style={styles.processIndicator}>
<TouchableOpacity disabled>
<Text style={styles.textProcessPrimary}>Previous</Text>
</TouchableOpacity>
<TouchableOpacity onPress={()=>Actions.RegisterEventThree({event_id: this.props.event.categories[0].event_id, category_id: this.state.event_id, size: this.state.size, address: this.state.addressx})}>
<Text style={styles.textProcessPrimary}>Next</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
</React.Fragment>
);
}
}
export default connect(
null,
{getAddresses},
)(RegisterEventOne);
The API :
export function getAddresses(data, callback) {
AsyncStorage.getItem('token').then(value => {
const token = JSON.parse(value);
fetch('https:apiurl.com', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'bearer' + token.access_token,
},
})
.then(response => response.json())
.then(response => callback(response.data))
.catch(error => callback(false, null, error.json()));
The loading indicator shows only if data(options) is undefined or null. Which means that you have no data at all, or data structure is bad.
You'v said that error alert is also triggered, which is not really a great thing. I don't know why the error is showing you some data tho. (except of error data).
Options should be passed in this format: ['data1', 'data2'].
Also, your taking the data from redux => this.props.event.categories instead of state. If you want to use redux, then you are missing some kind of mapStateToProps in connect fnc.
There is a lot of wrong patterns in this code. take a look at some examples of how to use redux and also take a look at examples in react-native-modal-dropdown github repo if you want to use that.
It's solved now .
I just added ,true,null behind response.data .
It would look like this :
.then(response => callback(response.data,true,null)

search box function using redux in react native

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.