use for loop in flatlist react native - javascript

I'm beginner in react native, and I want to use for loop in flatlist to push require data,
render() {
return (
<View style={styles.container}>
<FlatList
data={[
require("./assest/image1.jpg"),
require("./assest/image2.jpg"),
require("./assest/image3.jpg"),
]}
renderItem={({ item }) => {
return <ListItem image={item} />
}}
keyExtractor={
(index) => {return index}
}
/>
</View>
)
}
}
Like when pushing array from state using for loop
state ={
a: [12 , 13 , 14 ,15 , 19 ,21 ]
b: "1"
d = () => {
let c =[];
for (var i =0; i<= this.state.a.length - 1 ; i++) {
c.push( <child text = {this.state.a[i] />);
}
return c;
};
Is there anyway to use looping in flatlist or we can't using any looping in list or flatlist in
React Native.

You can define a state (array) and then loop through your required data and push them into the array state. Then, pass that state into the data prop of the FLatlist.
You can do something like this...
import React, { Component } from 'react';
import { View, FlatList } from 'react-native';
import ListItem from '...'; //import the ListItem here
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
}
}
componentDidMount = () => {
let data = [];
const images = {
image1: require("./assest/image1.jpg"),
image2: require("./assest/image2.jpg"),
image3: require("./assest/image3.jpg"),
}
images.forEach(image => {
data.push(image);
this.setState({ data })
})
}
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.data}
renderItem={({ item }) => {return <ListItem image={item} />}}
keyExtractor={(index) => {return index}}
/>
</View>
);
}
}
Here, when the component mounts, it loops through the 'images' object and push them into an array called 'data' and store it to the state. Then, that state is passed to the Flatlist as a prop.
Please go through this and ask me if you have any further questions regarding this.

Related

Function removes all items from Flatlist, instead of selected one

I'm learning React Redux at the moment and I'm working on a food list in which the user can add and remove items from a Flatlist, up until now I worked on adding the items, which works perfectly, now I'm using the same approach to remove the item from the global state foodList, I use onLongPress to start the function removeFromFoodList in the Diet screen. When I run the code and I proceed to remove the items instead of deleting the single item it deletes all the items in the Flatlist. Thank you for your help.
Diet
class Diet extends Component {
removeItem = () => {
let foodList = this.props.foodList;
this.props.removeFromFoodList(foodList)
}
render() {
return (
<FlatList
data={this.props.foodList}
renderItem={({item}) => (
<View>
<TouchableOpacity
onLongPress={this.removeItem}
>
<Text>{item.foodName}</Text>
<Text>
{item.calories}
</Text>
<MaterialIcons name="arrow-forward-ios" />
</TouchableOpacity>
</View>
)}
keyExtractor={item => item.id}
/>
}
}
function mapStateToProps(store){
return{
foodList: store.userState.foodList
};
}
const mapDispatchToProps = { removeFromFoodList };
export default connect(mapStateToProps, mapDispatchToProps)(Diet);
INDEX
import { ADD_FOOD, REMOVE_FOOD } from "../constants/index";
export const updateFoodList = (foodList) => {
return { type: ADD_FOOD, payload: foodList}
}
export const removeFromFoodList = (foodList) => {
return { type: REMOVE_FOOD, payload: foodList}
}
REDUCERS
import { ADD_FOOD, REMOVE_FOOD } from "../constants";
const initialState = {
foodList: [],
};
export const user = (state = initialState, action) => {
switch (action.type){
case ADD_FOOD:
return{
...state,
foodList: [...action.payload],
}
case REMOVE_FOOD:
return{
...state,
foodList: [...state.foodList.filter((item) => item.id != action.id)],
}
default:
return state
}
};
ARRAY EXAMPLE
Array [
Object {
"calories": "120",
"foodId": 0.8845240802796346,
"foodName": "Rice",
},
]
I'm not sure why it returns as empty, but there are a few problems I see here.
In your reducer:
[...state.foodList.filter((item) => item.id != action.id)]
If the structure of foodlist is as provided:
Object {
"calories": "120",
"foodId": 0.8845240802796346,
"foodName": "Rice",
},
]
Then it has no id key, and even if it does, action.id doesn't exist (only action.type and action.payload exist). Try console logging action and state.foodList under case REMOVE_FOOD: to get more detail.
On the component Diet this.props.foodList contain all data of the flatlist it's ok , you pass it to the flatlist to be rendered , alwais ok , but on each item of Flatlist you have added on each a onLongPress={this.removeItem} the function removeItem execute removeFromFoodList that you put this.props.foodList as a parameters to be removed .. that why all list are removed
to fix this you need to pass a item value to removeItem():
removeItem = (itemToremove) => {
this.props.removeFromFoodList(itemToremove)
}
render() {
return (
<FlatList
data={this.props.foodList}
renderItem={({ item }) => (
<View>
<TouchableOpacity
onLongPress={this.removeItem(item)}
>
<Text>{item.foodName}</Text>
<Text>
{item.calories}
</Text>
<MaterialIcons name="arrow-forward-ios" />
</TouchableOpacity>
</View>
)}
keyExtractor={item => item.id}
/>
)
}

How to re-render React Native Component after transferring prop to there

I'm trying to implement a list of users with searching by username possibility.
I've faced with the issue with re-rendering SearchListOfUsers after I change a prop usernameFilter in a parent Component SearchPeopleScreen and pass it to a child SearchListOfUsers.
I know that a component should re-render itself when its state is changed but in my case even state of child component doesn't change. How to update my child comp. SearchListOfUsers after I pass a prop usernameFilter?
Here is my parent comp. SearchPeopleScreen:
export default class SearchPeopleScreen extends Component {
constructor(props) {
super(props);
this.state = {
...
usernameFilter: ''
}
}
render() {
return(
<Container>
<Header style = {searchPeopleScreenStyle.header} searchBar>
<Title style = {searchPeopleScreenStyle.title}>
Search
</Title>
<Right/>
<Item style = {searchPeopleScreenStyle.searchFieldWrapper}>
<IconSimpleLine name = 'magnifier' color = {placeholder} size = {20} style = {{padding: 10}}/>
<TextInput
underlineColorAndroid = 'transparent'
onChangeText = {(text) => {
this.setState({usernameFilter: text});
}}
placeholder = 'Type username'
style = {searchPeopleScreenStyle.searchInput}
maxLength = {15}
/>
</Item>
</Header>
<Content>
<ScrollView contentContainerStyle = {searchPeopleScreenStyle.container}>
...
{/* Search screen's body */}
<SearchListOfUsers searchOption = {this.state.searchOption}
usernameFilter = {this.state.usernameFilter}/>
</ScrollView>
</Content>
</Container>
)
}
}
And here is my child comp. SearchListOfUsers:
export default class SearchListOfUsers extends Component {
constructor(props) {
super(props);
this.state = {
usersDataArray: [],
usernameFilter: this.props.usernameFilter
};
this.arrayHolder = [];
console.warn('1 - ' + this.state.usernameFilter)
}
componentDidMount() {
this.getAllUsersData()
console.warn(this.state.usernameFilter)
if(this.state.usernameFilter) {
this.filterUsers();
}
}
getAllUsersData = () => {
return new Promise((resolve, reject) => {
// getting users data and creating an array
...
allUsersDataArray.push({...});
this.setState({
usersDataArray: allUsersDataArray
});
resolve();
})
}
filterUsers = () => {
const newUsersDataArray = this.arrayHolder.filter((user) => {
const usernameInTheList = user.userUsername.toUpperCase();
const inputtedUsername = this.state.usernameFilter.toUpperCase();
return usernameInTheList.includes(inputtedUsername);
});
this.setState({
usersDataArray: newUsersDataArray
})
}
render() {
return(
<Content contentContainerStyle = {searchPeopleScreenStyle.listOfUsersWrapperGlobal}>
<FlatList
data = {this.state.usersDataArray}
keyExtractor = {(item) => (item.userId)}
renderItem = {({item}) => (
<UserListItem
country = {item.userCountry}
username = {item.userUsername}
...
/>
)}
/>
</Content>
)
}
}
}
If you need to filter your data based on selections from a parent component, you should also be filtering your collection there as well. Once you have filtered your collection, that should be passed to the child component.
The child component in this case should be purely presentational and static. It shouldn't care about filtering data or updating it's component state etc, it just wants to render out whatever props it is passed. searchOption, usernameFilter, dataCollection
You filter users in componentDidMount lifecyle method which means it will run only once on mounting process of child component.
You can filter in render method like
filterUsers = () => {
if(!this.props.usernameFilter.length) return this.state.usersDataArray
return this.state.usersDataArray.map((user) => {
const usernameInTheList = user.userUsername.toUpperCase();
const inputtedUsername = this.props.usernameFilter.toUpperCase();
return usernameInTheList.includes(inputtedUsername);
});
}
render() {
return(
<Content contentContainerStyle = {searchPeopleScreenStyle.listOfUsersWrapperGlobal}>
<FlatList
data = {this.filterUsers()}
keyExtractor = {(item) => (item.userId)}
renderItem = {({item}) => (
<UserListItem
country = {item.userCountry}
username = {item.userUsername}
...
/>
)}
/>
</Content>
)
}
}

Flat List not updated when data supplied with Redux (React Native)

My problem is that my flat list is not being updated when I add an element to "entriesPerDay" in my Redux store.
Both home screen and the Flat List have state mapped to props. I have tried:
- passing the data to EntriesList through props from Home Screen
- using the state from reducer as data provider of the EntriesList
Nothing seem to be working and the shouldComponentUpdate or any other relevant function is never called.
REDUCER:
case NEW_ENTRY_LOCAL:
let newState = {...state};
newState.entriesPerDay.push(action.entry);
return{
...newState
}
HOME SCREEN:
(...)
render() {
return (
<View style={{ flex: 1, alignItems: 'flex-start', justifyContent: 'flex-start' }}>
<NavBar onItemPressed={this.onItemPressedHandler}/>
<DayPicker onDatePicked={this.onDatePickedHandler} />
<TotalTime totalTime={this.props.total} />
<EntriesList entries={this.props.entriesPerDay}/>
<Timer onEntryEnd={this.onEntryEndHandler} onTimeChanged={this.onTimeChangedHandler} onEntryCreate={this.onEntryCreateHandler}/>
<Button title="clickkk" onPress={this.onItemPressedHandler}>CLICK ME</Button>
</View>
);
}
FLAT LIST:
class entriesList extends React.Component {
componentDidMount()
{
reactMixin(entriesList, TimerMixin);
this.timer = setInterval(() => {
console.log(this.props.entriesPerDay);
}, 3000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
shouldComponentUpdate(nextProps, nextState)
{
console.log("new props" + nextProps);
return true;
}
render()
{
return (
<FlatList style={styles.full}
data={this.props.entries}
extraData={this.props.entriesPerDay}
renderItem={
(info)=>(
<ListItem key={info.item.key}
startDateTime={info.item.startDateTime}
endDateTime = {info.item.endDateTime}
description = {info.item.description}
prevEntryEnd = {info.item.prevEntryEnd}
nextEntryStart = {info.item.nextEntryStart}
total = {info.item.totalTime}
/>
)
}
/>
);
}
}
const mapStateToProps = state => {
return {
serverCopy : state.entries.serverCopy,
entriesPerDay : state.entries.entriesPerDay,
pickedDate : state.entries.pickedDate,
total: state.entries.total,
local: state.entries.local
};
};
const mapDispatchToProps = dispatch => {
return {
onPickDate: (day) => dispatch(pickDay(day)),
onDataSet: (data) => dispatch(setData(data)),
onNewEntryLocal: (entry) => dispatch(newEntryLocal(entry)),
onEndEntryLocal: (entry) => dispatch(endEntryLocal(entry)),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(entriesList)
;
Try :
case NEW_ENTRY_LOCAL:
let newEntriesPerDay = state.entriesPerDay.concat(action.entry);
return {
...state,
entriesPerDay: newEntriesPerDay
}
It is because entriesPerDay was just beeing copied by reference in the newState in your previous example. redux and react compare the reference and see that it's the same so no re-render will happen. That's why you should copy it manually.
Note : Use concat instead of push to return a new array (new reference)

React Native display FlatList with Firebase data

Trying to get FlatList to display data from Firebase.
Setup is correct and I can see the date in my console, but don't know how to visualise it.
I'd like to see 'recipeOne' 'recipeTwo' 'recipeThree' in the list.
I am sure I am missing something basic.
Here is the code
...
import {DataConfig} from '../data/DataConfig';
const firebaseApp = firebase.initializeApp(DataConfig);
globalTexts = require('../styles/Texts.js');
globalColors = require('../styles/Colors.js');
export default class ListSort extends Component {
constructor(props) {
super(props);
this.dataItem = firebaseApp.database().ref('recipes');
this.state = {
item: []
}
};
componentWillMount() {
this._createItemList();
};
_createItemList = (dataItem) => {
this.dataItem.on('value', (snapshot) => {
var itemList = [];
snapshot.forEach((doc) => {
itemList.push({
key:doc.key,
itemType: doc.toJSON()
});
this.setState({item: itemList});
console.log(this.state.item);
})
})
};
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.item}
renderItem={({item, index}) => (
<View style={styles.cell}>
<Text style={globalText.btnFlatPrimary}>{item.recipes}</Text>
</View>
)}
/>
</View>
)
}
}
and here is the data. The rules in Firebase are setup as read:true only.
{
"recipes": {
"recipeOne": {...
"recipeTwo": {...
"recipeThree": {...
}
}

How to handle checkbox fetching from json using react-native-element checbox with FlatList React Native?

I'm trying to create dynamic checkbox with the name fetching from json, this issue looks same as I need, but without the code explaining, I can't archieve my goal,
I have a json example like this :
this.state = {
data : [
{
"name": "ALL",
},
{
"name": "Android",
},
{
"name": "iOS",
},
{
"name": "React Native",
}
]}
and with this code below:
<CheckBox
center
title={this.state.data[1].name}
onPress={() => {this.setState({checked: !this.state.checked})}}
checked={this.state.checked}
/>
the checkbox running well but it's just showing 2nd value of json
My Goal is to displaying all of json value into flatlist and makes checkbox running well,
For now I just can displaying those json into FlatList, but the checkbox is not works
import React, { Component } from 'react';
import {
Text, View, StyleSheet, Alert, FlatList
} from 'react-native';
import Dimensions from 'Dimensions';
import { CheckBox } from 'react-native-elements'
const DeviceWidth = Dimensions.get('window').width;
const DeviceHeight = Dimensions.get('window').height;
class MedicalClearlance extends React.Component {
constructor(props){
super(props);
this.state = {
checked:[],
data : [
{
"name": "ALL",
},
{
"name": "Android",
},
{
"name": "iOS",
},
{
"name": "React Native",
}
]}
}
render() {
return (
<FlatList
data={ this.state.data }
renderItem={({item, index}) =>
<CheckBox
center
title={item.name}
onPress={() => {this.setState({checked: !this.state.checked}), console.log(this.state.checked +' '+ index)}}
checked={this.state.checked}/>
}
/>
);
}
}
anyone can help me how to archieve my goal?
The answer that Ahsan Ali provided will work. However it is missing a very vital line of code.
Within the <FlatList/> component, be sure to add this extraData
={this.state}. This will allow the FlatList component to re-render whenever the state is changed.
The render method will then look like this:
handleChange = (index) => {
let checked = [...this.state.checked];
checked[index] = !checked[index];
this.setState({ checked });
}
render() {
let { data, checked } = this.state;
return (
<FlatList
data={data}
extraData={this.state}
renderItem={({ item, index }) =>
<CheckBox
center
title={item.name}
onPress={() => this.handleChange(index)}
checked={checked[index]} />
}
/>
);
}
By passing extraData={this.state} to FlatList we make sure FlatList
itself will re-render when the state.selected changes. Without setting
this prop, FlatList would not know it needs to re-render any items
because it is also a PureComponent and the prop comparison will not
show any changes.
More information can be found at React-Native Flat-List documentation here.
If you're using the code from Ahsun Ali's post, there may be another error you come across.
A warning error displays that the componentWillMount() method is
deprecated. In which case be sure to use the componentDidMount()
instead.
Hope this helps people!
You need to fill up the checked array in order to manipulate it after.
constructor() {
super();
this.state = {
data: [
{
"name": "ALL",
},
{
"name": "Android",
},
{
"name": "iOS",
},
{
"name": "React Native",
}
],
checked: []
}
}
componentWillMount() {
let { data, checked } = this.state;
let intialCheck = data.map(x => false);
this.setState({ checked: intialCheck })
}
and pass the index of the selected checkbox to update it
handleChange = (index) => {
let checked = [...this.state.checked];
checked[index] = !checked[index];
this.setState({ checked });
}
render() {
let { data, checked } = this.state;
return (
<FlatList
data={data}
renderItem={({ item, index }) =>
<CheckBox
center
title={item.name}
onPress={() => this.handleChange(index)}
checked={checked[index]} />
}
/>
);
}
I hope it helps!
you could try this for multiple selection, ref link-> https://facebook.github.io/react-native/docs/flatlist
class MyListItem extends React.PureComponent
{
_onPress = () => {
this.props.onPressItem(this.props.id);
};
render() {
const textColor = this.props.selected ? 'red' : 'black';
return (
<TouchableOpacity onPress={this._onPress}>
<View>
<Text style={{color: textColor}}>{this.props.title}</Text>
</View>
</TouchableOpacity>
);
}
}
class MultiSelectList extends React.PureComponent {
state = {selected: (new Map(): Map<string, boolean>)};
_keyExtractor = (item, index) => item.id;
_onPressItem = (id: string) => {
// updater functions are preferred for transactional updates
this.setState((state) => {
// copy the map rather than modifying state.
const selected = new Map(state.selected);
selected.set(id, !selected.get(id)); // toggle
return {selected};
});
};
_renderItem = ({item}) => (
<MyListItem
id={item.id}
onPressItem={this._onPressItem}
selected={!!this.state.selected.get(item.id)}
title={item.title}
/>
);
render() {
return (
<FlatList
data={this.props.data}
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
/>
);
}
}
for(const ele of this.state.selected.keys())
console.log(ele);
//**after that you could get all the selected keys or values from something like this**

Categories