I'm trying to display a flat list (values form json placeholder) filterable with a search bar and it's not rendering for some reason. The values are not visible. Thanks!
The flat list code:
import React, { Component } from "react";
import { View, Text, FlatList, Button } from "react-native";
import { ListItem, SearchBar } from "react-native-elements";
class FlatListDemo extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
temp: [],
error: null,
search: null
};
}
componentDidMount() {
this.getData();
}
getData = async () => {
const url = `https://jsonplaceholder.typicode.com/users`;
this.setState({ loading: true });
try {
const response = await fetch(url);
const json = await response.json();
this.setResult(json);
} catch (e) {
this.setState({ error: 'Error Loading content', loading: false });
}
};
setResult = (res) => {
this.setState({
data: [...this.state.data, ...res],
temp: [...this.state.temp, ...res],
error: res.error || null,
loading: false
});
}
renderHeader = () => {
return <SearchBar placeholder="Search Here..."
lightTheme round editable={true}
value={this.state.search}
onChangeText={this.updateSearch} />;
};
updateSearch = search => {
this.setState({ search }, () => {
if ('' == search) {
this.setState({
data: [...this.state.temp]
});
return;
}
this.state.data = this.state.temp.filter(function(item){
return item.name.includes(search);
}).map(function({id, name, email}){
return {id, name, email};
});
});
};
render() {
return (
this.state.error != null ?
<View style={{flexDirection: 'column',justifyContent: 'center', alignItems: 'center' }}>
<Text>{this.state.error}</Text>
<Button onPress={
() => {
this.getData();
}
} title="Reload" />
</View> :
<FlatList
ListHeaderComponent={this.renderHeader}
data={this.state.data}
keyExtractor={item => item.email}
renderItem={({ item }) => (
<ListItem
roundAvatar
title={`${item.name}`}
subtitle={item.email}
/>
)}
/>
);
}
}
export default FlatListDemo;
Importing this list to:
import React, {useState, useEffect} from 'react'
import { Text, View, StyleSheet, StatusBar, SafeAreaView } from "react-native"
import "firebase/auth";
import 'react-native-gesture-handler';
import "firebase/auth";
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
import FlatListDemo from './FlatListDemo';
const Home: () => React$Node = () => {
return(
<>
<StatusBar barStyle="dark-content"/>
<SafeAreaView style={{flex: 1}}>
<FlatListDemo/>
</SafeAreaView>
</>
);
};
export default Home;
This is what it looks like (values should be there). Using Expo on Android:
photo1
Thanks! I appreciate the help!
It seems to me that you are using a ListElement as it is defined in version 1.2.0 of react-native-elements but the actual version that you are using is > 1.2.0.
You are implementing it similar to the documentation of react-native-elements 1.2.0.
However, the definition of ListItem has changed in newer version. In the newest version, the ListItem component is just a simple view wrapper. Hence, it needs to contain children in order to display the information that you want.
In your case this could be implemented as follows (I did not know what roundAvatar is doing).
renderItem={({ item }) => (
<ListItem>
<ListItem.Content>
<ListItem.Title>{`${item.name}`}</ListItem.Title>
<ListItem.Subtitle>{item.email}</ListItem.Subtitle>
</ListItem.Content>
</ListItem>
Check the documentation of the newest version for the exact features that you want to use.
Related
It's not deleting anything and delete action isn't working
import React, {Component} from 'react';
import {
StyleSheet,
View,
FlatList,
Text,
TouchableOpacity,
SafeAreaView,
Button,
} from 'react-native';
import ApiCard from './ApiCard';
export default class ApiList extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
dataSource: [],
};
}
static navigationOptions = {
title: 'List of countries',
};
componentDidMount() {
fetch('https://restcountries.eu/rest/v2/all')
.then(response => response.json())
.then(responseJson => {
this.setState({
loading: false,
dataSource: responseJson,
});
})
.catch(error => console.log(error));
}
render() {
const {dataSource} = this.state;
const {navigation} = this.props;
return (
<SafeAreaView style={styles.container}>
<FlatList
data={dataSource}
keyExtractor={item => item.name}
renderItem={data => (
<ApiCard {...data.item} navigation={navigation} />
)}
/>
</SafeAreaView>
);
}
}
The below component is for data rendering as props:
import React from 'react';
import {TouchableOpacity, Text, StyleSheet, Button} from 'react-native';
const ApiCard = ({name, navigation, alpha2Code, population, capital}) => {
return (
<TouchableOpacity
style={styles.country}
onPress={() =>
navigation.push('CountryName', {
name,
alpha2Code,
population,
capital,
})
}>
<Text>{name}</Text>
<Text>{alpha2Code}</Text>
<Button title="del" />
Here I need a del button action :
</TouchableOpacity>
);
};
export default ApiCard;
I have created Table component. In this component i have created two buttons. one for download and second is share. both have onPress method. I have imported this Table component in the dashboard component. but I am unable to use both methods individually in my dashboard component.please suggest any solution for this problem.
Table Component:
import React, { StrictMode, useEffect, useState } from "react";
import { Text, View, ActivityIndicator } from "react-native";
import Size from "../../constants/Sizes";
import Strings from "../../constants/Strings";
import { Table, TableWrapper, Row, Rows } from "react-native-table-component";
import Color from "../../constants/Colors";
import Icon from "../../styles/Icons";
import api from "../../services/api";
import ListModel from "../ListModal";
import { TableTwoStyle as tableStyle } from "../../styles";
import { heightToDp } from "../../constants/Utils";
const TableTwo = (props) => {
const [files, setFiles] = useState([]);
const [modalState, setModalState] = useState(false);
useEffect(() => {
const fileData = api.getFileOptions();
setFiles(fileData);
}, []);
const { data } = props;
const handleOptions = (title) => {
console.log("title", title);
props.onPress(title);
// this.closeModal();
};
const openModal = () => {
setModalState(true);
};
const closeModal = () => {
setModalState(false);
};
return (
<StrictMode>
{data !== undefined ? (
<View style={tableStyle.mainContainer}>
<View style={tableStyle.HeadingSection}>
<View style={tableStyle.LabelContainer}>
<View style={tableStyle.leftSection}>
<Text style={tableStyle.labelText}>{Strings.tableTitle}</Text>
</View>
<View style={tableStyle.rightSection}>
<Icon.MaterialIcons
name="file-download"
color={Color.gray}
style={tableStyle.exportButton}
size={heightToDp(Size.per_4_5)}
onPress={openModal}
/>
</View>
<View style={tableStyle.rightSection}>
<Icon.MaterialIcons
name="share"
color={Color.info}
style={tableStyle.exportButton}
size={heightToDp(Size.per_4)}
onPress={openModal}
/>
</View>
</View>
<View style={tableStyle.divider} />
</View>
<View style={tableStyle.TableSection}>
{data.headers && data.headers.length > 0 ? (
<Table
borderStyle={{
borderWidth: Size.px_1,
borderColor: Color.dividerColor,
}}
>
<Row
data={data.headers}
flexArr={[Size.num_1]}
style={tableStyle.head}
textStyle={tableStyle.headerText}
/>
<TableWrapper style={tableStyle.wrapper}>
<Rows
data={data.data}
flexArr={[Size.num_1]}
style={tableStyle.row}
textStyle={tableStyle.text}
/>
</TableWrapper>
</Table>
) : (
<ActivityIndicator color={Color.loaderColor} size={Strings.lg} />
)}
</View>
<ListModel
modalState={modalState}
close={closeModal}
onPress={handleOptions}
data={files}
/>
</View>
) : null}
</StrictMode>
);
};
export default TableTwo;
Dashboard Component:
import React, { StrictMode, Component } from "react";
import { View, ScrollView } from "react-native";
import { GraphCardList as GraphList } from "../components";
import { InfoCardList as InfoList } from "../components";
import { TableTwo as Table } from "../components";
import Loader from "../components/Loader";
import Store from "../database/Storage";
import OptionsCard from "../components/Option";
import { Card as CardUI } from "../components";
import { dashboardStyle as dashboardUI } from "../styles";
import Api from "../services/api";
import inputValidation from "../helper/Validation";
import TableExport from "../exports/TableExport";
import Permission from "../services/AppPermission";
export default class DashboardScreen extends Component {
constructor(props) {
super(props);
this.state = {
tableList: [],
};
this.downloadData = this.downloadData.bind(this);
}
componentDidMount() {
}
componentWillUnmount() {
}
downloadData(title) {
...
}
shareData(){
....
}
render() {
const {
loader2,
infoList,
chartList,
tableList,
userList,
loader,
pauseState,
} = this.state;
//console.log("users",infoList);
if (loader) {
return (
<View style={dashboardUI.mainContainer}>
<Loader />
</View>
);
}
return (
<StrictMode>
<CardUI style={dashboardUI.Cards}>
<Table data={tableList} onPress={this.downloadData} />
</CardUI>
)}
</StrictMode>
);
}
}
If your'e passing same prop for two different buttons that means that the two buttons will execute the same method , but if you want to pass different methods for each button just pass a different props.
For example component B:
<View>
<Button title="Download" onPress={props.download}/>
<Button title="Share" onPress={props.share}/>
</View>
Component A:
<B download={this.downloadData} share={this.shareData}/>
Please try below code:
**In Dashboard Component:**
downloadData() {
}
`return (<Table data={tableList} handleDownloadData={this.downloadData} />);`
**In Table Component:**
const download = (data) => {
props.handleDownloadData(data);
};
const share = (data) => {
props.handleDownloadData(data);
};`
`return (<div><Button onClick={download}> Download</Button><Button onClick={share}> Share</Button></div>);
`
I have an issue with react-navigation in passing the props to another screen,
I need to pass some props to Detail screen when the user presses one of the List Places I need to push screen with some details about the place like a Name of place and Image of place,
Errors :
this is my Code
Reducer
import { ADD_PLACE, DELETE_PLACE } from "../actions/actionTypes";
const initialState = {
places: []
};
import placeImage from "../../assets/img.jpg";
const reducer = (state = initialState, action) => {
switch (action.type) {
case ADD_PLACE:
return {
...state,
places: state.places.concat({
key: Math.random(),
name: action.placeName,
// image: placeImage,
image: {
uri:
"https://images.unsplash.com/photo-1530009078773-9bf8a2f270c6?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80"
}
})
};
case DELETE_PLACE:
return {
...state,
places: state.places.filter(place => {
return place.key !== state.selectedPlace.key;
})
};
default:
return state;
}
};
export default reducer;
Place List Component
import React from "react";
import { FlatList, StyleSheet, ScrollView } from "react-native";
import ListItem from "../ListItem/ListItem";
const PlaceList = props => {
return (
<FlatList
style={styles.listContainer}
data={props.places}
renderItem={info => (
<ListItem
placeName={info.item.name}
placeImage={info.item.image}
onItemPressed={() => props.onItemSelected(info.item.key)}
/>
)}
keyExtractor={index => String(index)}
/>
);
};
export default PlaceList;
Find Place Screen
import React, { Component } from "react";
import { View, Text } from "react-native";
import { connect } from "react-redux";
import { StackActions } from "react-navigation";
import PlaceList from "../../Components/PlaceList/PlaceList";
class FindPlaceScreen extends Component {
constructor() {
super();
}
itemSelectedHandler = key => {
const selPlace = this.props.places.find(place => {
return place.key === key;
});
this.props.navigation.push("PlaceDetail", {
selectedPlace: selPlace,
name: selPlace.name,
image: selPlace.image
});
};
render() {
return (
<View>
<PlaceList
places={this.props.places}
onItemSelected={this.itemSelectedHandler}
/>
</View>
);
}
}
const mapStateToProps = state => {
return {
places: state.places.places
};
};
export default connect(mapStateToProps)(FindPlaceScreen);
Place Details Screen
import React, { Component } from "react";
import { View, Text, Image, TouchableOpacity, StyleSheet } from "react-native";
import Icon from "react-native-vector-icons/Ionicons";
class PlaceDetail extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View style={styles.modalContainer}>
<View>
<Image
source={this.props.navigation.state.params.image}
style={styles.placeImage}
/>
<Text style={styles.placeName}>
{this.props.navigation.state.params.namePlace}
</Text>
</View>
<View>
<TouchableOpacity onPress={props.onItemDeleted}>
<View style={styles.deleteButton}>
<Icon size={30} name="ios-trash" color="red" />
</View>
</TouchableOpacity>
<TouchableOpacity onPress={props.onModalClosed}>
<View style={styles.deleteButton}>
<Icon size={30} name="ios-close" color="red" />
</View>
</TouchableOpacity>
</View>
</View>
);
}
}
export default PlaceDetail;
You need to use react-native-navigation v2 for the find place screen
itemSelectedHandler = key => {
const selPlace = this.props.places.find(place => {
return place.key === key;
});
Navigation.push(this.props.componentId, {
component: {
name: 'PlaceDetail',
options: {
topBar: {
title: {
text: selPlace.name
}
}
},
passProps: {
selectedPlace: selPlace
}
}
});
};
make sure you import { Navigation } from "react-native-navigation";
Your PlaceDetail has some error
<TouchableOpacity onPress={props.onItemDeleted}>
<TouchableOpacity onPress={props.onModalClosed}>
Change props to this.props
<TouchableOpacity onPress={this.props.onItemDeleted}>
<TouchableOpacity onPress={this.props.onModalClosed}>
But I don't see onItemDeleted and onModalClosed anywhere, don't forget to pass those to PlaceDetail via props as well :)
I am building an app in react native and I am using Lisview to display some data for some strange reason the endReached is triggered itself without me scrolling the listview and the listView ends up displaying all items at first like I have incremented page value each time, also i get duplicate results for first api call with value page 1.
Code:
import React, {Component} from 'react';
import {Alert, ListView, Text, View} from 'react-native';
import categoryApi from './category.api';
import styles from './category.styles';
import CategoryItem from './category.items.component';
import ShopsNear from "../listshops/list-shops.component";
export default class Category extends React.Component {
constructor(props) {
super(props);
this.state = {
rawData: [],
isLoading: false,
categories: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2
}),
page: 1,
};
}
static navigationOptions = {
headerTitle: 'Categories',
title: 'Categories',
};
componentDidMount() {
this.fetchCategories();
}
fetchCategories() {
this.setState({isLoading: true});
categoryApi.getOne(this.state.page).then(response => {
if (response.data) {
this.setState({
rawData: this.state.rawData.concat(response.data.data),
categories: this.state.categories.cloneWithRows(this.state.rawData.concat(response.data.data)),
isLoading: false,
});
} else {
this.setState({isLoading: false});
Alert.alert(
'Something wrong happened!',
'My Alert Msg',
[],
{cancelable: true}
)
}
});
}
componentWillMount() {
}
showMore = () => {
this.setState({page: this.state.page + 1});
console.log("End reached... page: " + this.state.page);
this.fetchCategories();
};
render() {
const {navigate} = this.props.navigation;
return (
<View style={styles.container}>
<View style={styles.projektiHeader}>
<Text style={styles.projekti}>VALITSE PROJEKTI</Text>
</View>
<View style={styles.categoriesList}>
<ListView
dataSource={this.state.categories}
renderRow={(rowData) => <CategoryItem navigate={navigate} item={rowData}/>}
renderSeparator={(sectionId, rowId) => <View key={rowId} style={styles.separator}/>}
onEndReached={this.showMore}
/>
</View>
<View style={styles.shopsNear}>
<ShopsNear navigate={navigate}/>
</View>
</View>
);
}
}
Basically showMore() is itself, Anyone knows what's happening here?
I am trying to achieve so everytime I scroll and reaches the end of listview to call the showMore function which will fetch data from an API.
check the onEndReachedThreshold props for listView component.
I'm working on a very simple react-native app where I type the name of an artist in a searchbox, retrieve a list of artists from the spotify API and I display this list in FlatList component.
I manage to get the list of artists and I want to save it in the local state so that I pass it to the FlatList component.
The list object looks like this : [{...}, {...}, {...}, {...}]
But it doesn't seem to work and I think that my state is not updating and I don't know what I'm doing wrong.
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
FlatList,
StatusBar,
TextInput,
} from 'react-native';
import colors from './utils/colors';
import { List, ListItem, SearchBar } from 'react-native-elements';
import { searchArtist } from './utils/fetcher';
import { debounce } from 'lodash';
export default class spotilist extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
query: '',
artists: [],
error: null,
refreshing: false,
};
}
render() {
return (
<View style={ styles.container }>
<StatusBar barStyle="light-content" />
<TextInput style={ styles.searchBox }
value={this.state.value}
onChangeText={ this.makeQuery }
/>
<List>
<FlatList
data={this.state.artists}
//renderItem={({item}) => <Text>{item.name}</Text>}
/>
</List>
// {
// this.state.artists.map(artist => {
// return (
// <Text key={artist.id}>{artist.name}</Text>
// )
// })
// }
</View>
);
}
makeQuery = debounce(query => {
searchArtist(query)
.then((artists) => {
console.log(artists); // I have the list
this.setState({
artists: this.state.artists,
});
})
.catch((error) => {
throw error;
});
}, 400);
}
Thank you for your help.
UPDATE
I also tried using this without success :
<List>
<FlatList
data={this.state.artists}
renderItem={({ item }) => (
<ListItem
roundAvatar
title={item.name}
avatar={{ uri: item.images[0].url }}
/>
)}
/>
</List>
In the makeQuery function you need to set the response from the server like..
makeQuery = debounce(query => {
searchArtist(query)
.then((artists) => {
console.log(artists); // I have the list
this.setState({
artists: artists, //Here is the change
});
})
.catch((error) => {
throw error;
});
}, 400);