A little inexperienced here. Trying to render data with React Native Flatlist.
Here is my data:
data = {
-LYIaWAxkQA38DAbC3By: {hours: "6", type: "Welding"}
-LYIab-Ys9WkUNHE2cqL: {hours: "2", type: "Hair Drying"
}
I am trying to use:
<FlatList
data=data
renderItem={
(item) => <Text>{item.type}</Text>
}
keyExtractor={(item, index) => index.toString()}
/>
I want to be able to create a component that is able to use each type and hours.
I keep getting error, 'Invariant Violation: Tried to get frame for out of range index NaN'
Appreciate any help.
Try using an array:
const data = [
{
hours: "6",
type: "Welding",
identifier: "-LYIaWAxkQA38DAbC3By",
id: 1
},
{
hours: "2",
type: "Hair Drying",
identifier: "-LYIab-Ys9WkUNHE2cqL",
id: 2
}
]
<FlatList
data=data
renderItem={
(item) => <Text>{item.type}</Text>
}
keyExtractor={(item, index) => item.id.toString()}
/>
are you using firebase? if yes, you can use forEach
componentDidMount(){
this._convert();
}
_convert = () => {
let ALL_DATA = this.state.data;
let CONVERTED_DATA = [];
ALL_DATA.forEach( (individu_Items) => {
CONVERTED_DATA.push(individu_Items)
}
this.setState({flatlist_data: CONVERTED_DATA})
}
transform your object in an array:
data = Object.keys(data).map((key) => data[key]));
Related
I using react-native-searchable-dropdown library , but if user write string with its not in item array I receive white screen.
How I can add no result text (or its best option button who create missing option)?
If you are using flatlist to list all your data. There is a prop called ListEmptyComponent
import React from 'react',
import {FlatList, Button, Text} from 'react-native',
const emptyComponent = () => {
return(
<Text>Search result not found</Text>
<Button title='Do Something'/>
)
};
<FlatList
istEmptyComponent={emptyComponent}
/>
This will display if the search results where not found.
Actually this is work , just i need to add some details , its need to be change the same Searchable dropdown file:
const oldSupport = [
{ key: 'keyboardShouldPersistTaps', val: 'always' },
{ key: 'nestedScrollEnabled', val : false },
{ key: 'style', val : { ...this.props.itemsContainerStyle } },
{ key: 'data', val : this.state.listItems },
{ key: 'keyExtractor', val : (item, index) => index.toString() },
{ key: 'renderItem', val : ({ item, index }) => this.renderItems(item, index) },
{ key: 'ListEmptyComponent', val : () =>this.emptyComponent()}
I added :
{ key: 'ListEmptyComponent', val : () =>this.emptyComponent()}
after that i just add
emptyComponent = () => {
return(
<View>
<Text>Search result not found</Text>
<Button title='Do Something'/>
</View>
);
};
and in function
emptyComponent
you can do whatever you want
I want to show list of images on my app horizontally. I know if I give prop to my flat list horizontal ={true} it will be horizontal but the problem is that FlatList not showing images at all. This is what I have tried so far
const data = [
{
imageUrl: "https://c7.uihere.com/files/45/824/935/united-states-win-the-white-house-hotel-business-company-refresh-icon-thumb.jpg",
id:"1"
},
{
imageUrl: "http://via.placeholder.com/160x160",
id:"2"
},
{
imageUrl: "http://via.placeholder.com/160x160",
id:"3"
},
{
imageUrl: "http://via.placeholder.com/160x160",
id:"4"
},
{
imageUrl: "http://via.placeholder.com/160x160",
id:"5"
},
{
imageUrl: "http://via.placeholder.com/160x160",
id:"6"
}
];
export default class CircularImage extends Component {
constructor(props) {
super (props)
this.state = {
data:data
}
}
render() {
return (
<FlatList
data = {this.state.data}
renderItem = {({item}) => {
<Image styel = {styles.circularImage} source = {{uri : item.imageUrl}}/>
}}
keyExtractor ={item => {item.id.toString()}}
/>
)
}
}
You are missing a return statement in your renderItem function
<FlatList
data = {this.state.data}
renderItem = {({item}) => {
return <Image styel = {styles.circularImage} source = {{uri : item.imageUrl}}/>
}}
keyExtractor ={item => {item.id.toString()}}
/>
OR
<FlatList
data = {this.state.data}
renderItem = {({item}) => <Image styel = {styles.circularImage} source = {{uri : item.imageUrl}}/>
}
keyExtractor ={item => {item.id.toString()}}
/>
In React Native, image has to have width and height in order to show. You might missed out of that part.
I am developing an app with react-native , using RESTfull api with laravel backend , I have an object that has arrays in it . I am using it to create user's profile page . but I don't know how to render those arrays.
here is my api response:
{
meta: {
code: 200,
message: 'Success',
errors: []
},
data: {
users: [
{
personal_information: {
full_name: 'hesam sameni',
avatar: 'https://aaa/file/image/hesamsameni.jpeg',
rate: '0.0',
phone: [],
location: {
name: 'something',
lat: 00,
long: 00,
address: 'something',
distance: 00
},
about: {
quote: 'something',
bio: 'something'
},
topics: {
a: 'a',
b: 'b',
c: 'c',
d: 'd'
},
stats: {
a: 10,
b: 0,
c: 0,
d: 0,
e: 0
},
experiences: [
{
title: 'something',
organization: 'something',
start: 'something',
end: 'something'
}
],
educations: [
{
title: 'something1',
university: 'something1',
major: 'something1',
start: 'something1',
end: 'something1'
},
{
title: 'something2',
university: 'something2',
major: 'something2',
start: 'something2',
end: 'something2'
}
]
}
}
]
}
};
For example how can I show educations in user's profile?
here is the render method ( I already got data from api and stored in state {this.state.dataSource}
render method:
render() {
return (
<View>
<FlatList
data={this.state.dataSource}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => (
<View>
<Text>Name: {item.personal_information.full_name}</Text>
<Text>Rate: {item.personal_information.Rate}</Text>
<Text>Educations:</Text>
// Here I need to display all of user's educations
</View>
)}
/>
</View>
);
}
I am not sure if I had to use flatlist since it is only data for 1 specific user , but I didn't know how to render data in other way than flatlist .
try this it will help you achive what you want.
if not tell me..
<FlatList
data={this.state.itemArray}
keyExtractor={(item, index) => index.toString()}
renderItem={({item}) =>{
console.warn(item.data.users[0].personal_information.educations)
return(<FlatList
data={item.data.users[0].personal_information.educations}
keyExtractor={(item, index) => "D"+index.toString()}
renderItem={({item}) =>{
console.warn(item)
}
}/>)
}
}/>
if u want to get something from personal_information
try this example : console.warn(item.data.users[0].personal_information.full_name)
So .map itself only offers one value you care about... That said, there are a few ways of tackling this:
// instantiation
this.state.dataSource
//Using `.map` directlly
this.state.dataSource.map((obj, index)=> {
console.log(obj);
return(
<View />
)
});
// what's built into Map for you
this.state.dataSource.forEach( (val, key) => console.log(key, val) );
// what Array can do for you
Array.from( this.state.dataSource ).map(([key, value]) => ({ key, value }));
// less awesome iteration
let entries = this.state.dataSource.entries( );
for (let entry of entries) {
console.log(entry);
}
Note, I'm using a lot of new stuff in that second example... ...Array.from takes any iterable (any time you'd use [].slice.call( ), plus Sets and Maps) and turns it into an array... ...Maps, when coerced into an array, turn into an array of arrays, where el[0] === key && el[1] === value; (basically, in the same format that I prefilled my example Map with, above).
I'm using destructuring of the array in the argument position of the lambda, to assign those array spots to values, before returning an object for each el.
If you're using Babel, in production, you're going to need to use Babel's browser polyfill (which includes "core-js" and Facebook's "regenerator").
I'm quite certain it contains Array.from.
render(){
console.log(this.state.data.users[0].personal_information.educations,'cdscdscdcds')
return(
<div>
{this.state.data.users.map((value)=>{
console.log(value,'cd')
})}
</div>
I am rendering data fetched from an api response.
I want to be able to compare the current row being rendered with the last one.
Example: comparing item day with the last item. to be able to insert a separator of the day.
this is just a simple example of what I am trying to do.
//data
const array = [
{day: '3/14', name: 'item1'},
{day: '3/14', name: 'item2'},
{day: '3/14', name: 'item3'},
{day: '3/15', name: 'item4'}
]
if new day, I will insert a separator. the intention is to group data by day.
let lastDay = null;
renderRows(item, index) {
//conditions
let day = item.day;
if(day != lastDay) daySeparator = true;
//store last day
lastDay = day;
return (
<ListItem noIndent style={style.listRow}>
<Row style={[style.tableRow,{alignItems: 'center'}]}>
<Text>{item.name}</Text>
</Row>
</ListItem>
);
}
My problem is that renderRows does not work like for loops, it render each item as separate without being able to keep track of previous rendered items.
is it possible to do it as so, or do I need to manipulate the array before passing it to RenderRows? if so, what's the most optimal way to do it, foreach? for loop?
Now that your question is more clear I can suggest you to use something like <SectionList> (see doc).
In order to use a SectionList you have to pass it a sectioned array. With the data structure you posted I would group items by day:
const array = [
{ day: "3/14", name: "item1" },
{ day: "3/14", name: "item2" },
{ day: "3/14", name: "item3" },
{ day: "3/15", name: "item4" }
];
const grouped = array.reduce(
(result, item) => ({
...result,
[item["day"]]: [...(result[item["day"]] || []), item]
}),
{}
);
const sectionedList = Object.keys(grouped).map(item => ({
title: item,
data: grouped[item]
}));
Which will give you the following structure:
[
{
title: "3/14",
data: [
{ day: "3/14", name: "item1" },
{ day: "3/14", name: "item2" },
{ day: "3/14", name: "item3" }
]
},
{
title: "3/15",
data: [{ day: "3/15", name: "item4" }]
}
];
Now you can use it in a <SectionList>, for example:
<SectionList
renderItem={({item, index, section}) => {...}}
renderSectionHeader={({section: {title}}) => (
<Text style={{fontWeight: 'bold'}}>{title}</Text>
)}
sections={sectionedList}
keyExtractor={(item, index) => item + index}
/>
This way you can properly customize everything.
I really hope this could help you!
One option is to make a new array with map from your initial array. Hope this will get you on the right direction :)
const array = [1, 2, 3, 4]
export default class App extends React.Component {
render() {
const newArr = array.map ((item, idx) => {
const newItem = idx === array.length - 1 ? 'Gotta keep them separated' : item
return <Text>{newItem}</Text>
})
return (
<View>
{newArr}
</View>
);
}
}
Here's a working expo snack
I need to render two items "clientcalendarscreenred" and "nutritiondata" in a FlatList
PS: I am getting the two data "clientcalendarscreenred" and "nutritiondata" from a reducer through mapStateToProps
<FlatList
data={this.props.clientcalendarscreenred }
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
ItemSeparatorComponent={this._renderSeparator}
refreshing={this.state.refreshing}
onRefresh={this._onRefresh}
/>
===========
GETTING The DATA
===============
const mapStateToProps = ({clientcalendarscreenred, maincalendarreducer}) => {
const { client_id, workout_date, display_date } = maincalendarreducer;
return {
clientcalendarscreenred: clientcalendarscreenred.data,
nutritiondata: clientcalendarscreenred.nutrition,
};
};
You can use section list for this scenario.
You can also render the list heterogeneous or homogeneous i.e if you wish to render your sections differently
<SectionList renderSectionHeader={({section}) => this._renderHeader(section.data)}
sections={[
{
key: 'RedData',
data: clientcalendarscreenred.data,
renderItem: ({item}) => this.renderRedData(item)
},
{
key: 'NutritionData',
data: clientcalendarscreenred.nutrition,
renderItem: ({item}) => this.renderNutrition(item, index, section)
},
]}
keyExtractor={(item, index) => index}
/>
Something like below should work for you to print items from data prop in FlatList.Similarly you can pass nutritiondata to FlatList and use it to display.
const FlatList=(props)=>{
const {data, ...rest}=props;
const toRender= data&&data.length>0?data.map(item=><div>{item.something}</div>:<div/>
return toRender
}