React native looping through array - arrays

I have array of colors that is being rendered with a flatlist. The flatlist data is coming from remote url. The colors are hardcoded in the app. The issue is that I am having is that the json data that is coming from api contain more rows of data than the colors I have in a array which result in only 5 items showing. Can someone help me with allowing the colors to repeat (make the index of colors repeat over and over)
componentDidMount() {
fetch('https://reactnative.dev/movies.json')
.then((response) => response.json())
.then((json) => {
this.setState({data: json.movies});
})
.catch((error) => console.error(error))
.finally(() => {
this.setState({isLoading: false});
});
}
render() {
const Colors = ['#1abc9c', '#9b59b6', '#7b59f9'];
const {data, isLoading} = this.state;
return (
<SafeAreaView style={{flex: 1, padding: 24}}>
{isLoading ? (
<ActivityIndicator />
) : (
<FlatGrid
itemDimension={130}
data={data}
style={styles.gridView}
keyExtractor={({id}, index) => id}
// staticDimension={300}
// fixed
spacing={10}
renderItem={({item, index}) => (
<View
style={[
styles.itemContainer,
{backgroundColor: Colors[index]},
]}>
<Text style={{color: 'white'}}>{item.title}</Text>
<Text style={{color: 'white'}}>{item.releaseYear}</Text>
</View>
)}
/>
)}
</SafeAreaView>

Simply use a modulo: {backgroundColor: Colors[index % Colors.length]}
const Colors = ["#1abc9c", "#9b59b6", "#7b59f9"];
for (let i = 0; i < 10; i++) {
console.log(Colors[i % Colors.length]);
}

Related

Impossible to display the data after a get request react native

i'm trying to display information of a restaurant in my react-native app after i get it by a get request from my database. I don't have problem getting the data, it's the display the problem.
Inside my component RestaurantDetailScreen :
componentDidMount() {
this.getRestaurantInfo()
}
getRestaurantInfo = async () => {
try {
let res = await axios({
method: 'get',
url: `${environment.apiDevUrl}/restaurant/${this.state.restaurantId}`,
})
this.setState({
restaurantInfo: res.data,
})
console.log(this.state.restaurantInfo.restaurant.nom);
} catch (error) {
console.error(error)
}
}
The console log display my state with correct data from my backend, but when I try to render it inside my Flatlist there is nothing to display:
<ScrollView style={styles.container}>
{/* <Text>{this.state.restaurantInfo.restaurant.nom}</Text> */}
<FlatList
data={this.state.restaurantInfo}
renderItem={this.renderRestaurantInfo}
keyExtractor={item => `${item.restaurant.id}`}
/>
<SectionList
sections={productData}
ItemSeparatorComponent={this.renderSeparator}
renderItem={this.renderRestaurantDetail}
renderSectionHeader={({section: {header}}) => (
<Text style={styles.sectionHeader}>{header}</Text>
)}
keyExtractor={(item, index) => `${item.id}` + index}
ref={ref => (this.sectionListRef = ref)}
getItemLayout={this.getItemLayout}
/>
</ScrollView>
So i've tried to simply display the name of a restaurant inside a Text component like in the getRestaurantInfo() method but it will return a undefined if i don't remove it.
The render method renderRestaurantInfo() :
renderRestaurantInfo = ({item}) => (
<View style={styles.containerRestaurantInfo}>
{console.log('item : ', item)}
<ItemRestaurantInfo
// image={item.restaurant.image}
title={item.restaurant.nom}
description={item.restaurant.description}
categories={item.restaurant.categorie}
adress={item.restaurant.adresse.rue1}
scheduleBeginning={item.restaurant.horaires.crenaux.hDebut}
scheduleEnd={item.restaurant.horaires.crenaux.hFin}
/>
</View>
)
And finally the ItemRestaurantInfo component :
ItemRestaurantInfo = ({
image,
title,
categories,
adress,
description,
scheduleBeginning,
scheduleEnd,
}) => {
return (
<View>
{/* <Image source={image} style={styles.topImage} /> */}
<View style={{padding: 15}}>
<Text style={styles.restaurantTitle}>{title}</Text>
<Text style={styles.restaurantInfoText}>{`${categories}`}</Text>
<View style={styles.viewInRow}>
<Image
style={{margin: 5}}
source={require('../../assets/icons/map-pin.png')}
/>
<Text style={styles.restaurantInfoText}>{adress}</Text>
</View>
<Text style={styles.restaurantInfoText}>{description}</Text>
<View style={styles.viewInRow}>
<Image
style={{margin: 5}}
source={require('../../assets/icons/calendar.png')}
/>
<Text style={styles.restaurantInfoText}>{scheduleBeginning} - {scheduleEnd}</Text>
</View>
</View>
</View>
)
}
You forget to pass item in your FlatList renderItem:
<FlatList
data={this.state.restaurantInfo}
renderItem={({item}) => this.renderRestaurantInfo(item)}
...
/>
You could also return a Component instead of method:
const RenderItems = ({ title }) => {
return (
<View>
<Text>{title}</Text>
</View>
);
}
...
// Pass the component to your FlatList
<FlatList
data={YOURDATA}
renderItem={({ item }) => <RenderItems title={item.title} />}
...
/>
And same thing goes for your SectionList
Edit: Working condeSandbox example with data fetch.
Ok I have finally find the solution, it was because my array restaurantInfo in the state was transform in an object when I use setState in the call of my backend... so inside the render method of the flatList there was no data.
OLD CODE
getRestaurantInfo = async () => {
try {
let res = await axios({
method: 'get',
url: `${environment.apiDevUrl}/restaurant/${this.state.restaurantId}`,
})
this.setState({
restaurantInfo: res.data,
})
} catch (error) {
console.error(error)
}
}
NEW CODE
getRestaurantInfo = async () => {
try {
let res = await axios({
method: 'get',
url: `${environment.apiDevUrl}/restaurant/${this.state.restaurantId}`,
})
let newArray = [...this.state.restaurantInfo];
newArray[0] = res.data
this.setState({
restaurantInfo: newArray,
})
console.log('state dans getResturantinfo:',this.state.restaurantInfo);
} catch (error) {
console.error(error)
}
}
With this syntax it force react to keep an array. And finally it was not necessery to use this syntax : renderItem={({item}) => this.renderRestaurantInfo(item)}
In my code I keep it like this :
<FlatList
data={this.state.restaurantInfo}
renderItem={this.renderRestaurantInfo}
keyExtractor={item => `${item.restaurant.id}`}
/>

Delete data from API(jsonplaceholder) on ReactNative

I’m trying to delete user from jsonplaceholder, because I want to delete item with helping click>
/This is official docs/
Delete a resource
fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'DELETE'
})
Important: the resource will not be really deleted on the server but it will be faked as if.
/My code/
export default function App() {
const [users, setUsers] = useState();
const pressHandler = (id) => {
fetch(`https://jsonplaceholder.typicode.com/users/${id}`, {
method: 'DELETE'
})
.then(() => {
// Issue GET request after item deleted to get updated list
// that excludes user of id
return fetch(`https://jsonplaceholder.typicode.com/users`)
})
.then(res => res.json())
.then(res => {
setUsers(res);
})
}
/* request API to json.placeholder to get users */
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(res => res.json())
.then(res => {
setUsers(res);
})
})
I’m trying in another way
export default function App() {
const [users, setUsers] = useState();
const pressHandler = (id) => {
setUsers((prevUsers)=>{
return prevUsers.filter(users => users.id != id)
})
}
}
but it want to remove((
this is my App component
return (
<View style={styles.container}>
<Header />
<View style={styles.content}>
{/* to form */}
<View style={styles.list}>
<FlatList
keyExtractor={item => item.id.toString()}
data={users}
renderItem={({item}) => (
<UserItem item={item} pressHandler={pressHandler}/>
)}
/>
</View>
</View>
</View>
and UserItem component
export default function UserItem({ item, pressHandler }){
return (
<View style={styles.item}>
<TouchableOpacity onPress={() => pressHandler(item.id)}>
<Text style={styles.main}>Employee: {item.name}</Text>
<Text style={styles.company}>Company: {item.company.name}</Text>
<Text style={styles.rest}>City: {item.address.city}, street: {item.address.street}</Text>
<Text style={styles.rest}>email: {item.email}</Text>
</TouchableOpacity>
</View>
)
}

How to show only one specific user and not all in Firebase?

I'm building a chat app using React Native and Firebase, All code is fine, but I want to show only one user in the list.
How to show only one specific user and not all?
For example:
Peter
John
Michael
Antony
Administrator
I want show Administrator, not all users.
state = {
users:[] }
componentWillMount(){
let dbRef = firebase.database().ref('users');
dbRef.on('child_added', (val) => {
let person = val.val();
person.phone = val.key;
if(person.phone===User.phone){
User.name = person.name
} else {
this.setState((prevState) => {
return {
users: [...prevState.users, person]
}
})
}
}) }
renderRow = ({item}) => {
return (
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Chat', item)}
style={{padding:10, fontSize: 16, color:'#00F0C8', borderBottomColor: '#ccc', borderBottomWidth:1}}>
<Text style={{fontSize:20}}>{item.name}</Text>
</TouchableOpacity>
) }
render(){
return(
<SafeAreaView>
<Text>These are the Users list</Text>
<Card style={styles.maincard}>
<FlatList
data={this.state.users}
renderItem={this.renderRow}
keyExtractor={(item) => item.phone}
/>
</Card>
</SafeAreaView>
)}
Well, you can try to filter the list,
render(){
return(
<SafeAreaView>
<Text>These are the Users list</Text>
<Card style={styles.maincard}>
<FlatList
data={this.state.users.filter(elem => elem.name === "Administrator")}
renderItem={this.renderRow}
keyExtractor={(item) => item.phone}
/>
</Card></SafeAreaView>)}

Select single row of Flatlist React native

Hey guys Im making a custom size picker I want to select single size at a time but onPress all item got changed..
my onPress event
onPressItemSize = (item,index:string) => {
this.setState((item) => {
const xl =
xl == item ? this.setState({xl:true}) : this.setState({xl:false});
return { xl };
});
this.setState({selectedSize:item.value})
};
and this is my flatlist component
<FlatList
data={this.state.label}
numColumns={5}
keyExtractor={(item, index) => index.toString()}
extraData={this.state}
renderItem={({item,index}) =>
<View style={{padding:10,}}>
<TouchableOpacity
onPress={this.onPressItemSize.bind(this, item,index)}
style={[styles.Buttoncolor,this.state.xl?null:styles.onfocusbutton]}>
<Text adjustsFontSizeToFit
textTransform='uppercase'
style={[styles.textcolor,this.state.xl?null:styles.white]}>
{item.label}
</Text>
</TouchableOpacity>
</View>
}
/>
Im not sure which state are you trying to set but you need to keen in mind that calling setState will trigger an async function and you need to wait until the new state is successfully changed. i would also use arrow functions for not binding the functions when calling them.
onPressItemSize = (item, index) => {
const { xl } = this.state; //what is xl ?? im assuming it is in your state
const callback = () => {console.log("State changed");}
var newXL = false;
if(xl === item){
newXL = true
}
//you can set diferents values at the same time
this.setState({xl: newXL, selectedSize: item.value }, callback)
};
<FlatList
data={this.state.label}
numColumns={5}
keyExtractor={(item, index) => index.toString()}
extraData={this.state}
renderItem={({item, index}) =>
<View style={{padding:10,}}>
<TouchableOpacity
onPress={() => onPressItemSize(item, index)} //changed
style={[styles.Buttoncolor,this.state.xl?null:styles.onfocusbutton]}>
<Text adjustsFontSizeToFit
textTransform='uppercase'
style={[styles.textcolor,this.state.xl?null:styles.white]}>
{item.label}
</Text>
</TouchableOpacity>
</View>
}
/>

react navigation custom tabBarComponent?

the navigationOptions code like that.
static navigationOptions = ({navigation})=>({
tabBarLabel:'查看',
headerTitle:navigation.state.params.title,
tabBarIcon: ({ tintColor,focused }) => (
<Image style={SKIN.tabImage} source={focused?AppImages.MyPost.lookchoose:AppImages.MyPost.look}/>
),
});
this is my Tab componet,how I can get tabBarLabel and tabBarIcon?
export default class Tab extends Component {
renderItem = (route, index) => {
const {
navigation,
jumpToIndex,
} = this.props;
const focused = index === navigation.state.index;
const color = focused ? this.props.activeTintColor : this.props.inactiveTintColor;
return (
<TouchableOpacity
key={index}
style={styles.tabItem}
onPress={() => jumpToIndex(index)}
>
<View
style={styles.tabItem}>
{this.props.renderIcon(color,focused)}
<Text style={{ color }}>{this.props.getLabel()}</Text>
</View>
</TouchableOpacity>
);
};
render(){
console.log('Tab this.props',this.props);
const {navigation,} = this.props;
const {routes,} = navigation.state;
return (
<View style={styles.tab}>
{routes && routes.map(this.renderItem)}
</View>
);
}
}
I custom Tab,now I want use that but some bug show me.
like that,
imagebug
please help me...
try updating the render method with this code:
render(){
console.log('Tab this.props',this.props);
const {navigation,} = this.props;
const {routes,} = navigation.state;
return (
<View style={styles.tab}>
//pass down the route and the index to the renderItem function
{routes && routes.map((route,index) => this.renderItem(route, index) )}
</View>
);
renderItem = (route, index) => {
const {
navigation,
jumpToIndex,
} = this.props;
const focused = index === navigation.state.index;
const color = focused ? this.props.activeTintColor : this.props.inactiveTintColor;
let TabScene = {
focused:focused,
route:route,
tintColor:color
};
return (
<TouchableOpacity
key={route.key}
style={styles.tabItem}
onPress={() => jumpToIndex(index)}
>
<View
style={styles.tabItem}>
{this.props.renderIcon(TabScene)}
<Text style={{ color }}>{this.props.getLabel(TabScene)}</Text>
</View>
</TouchableOpacity>
);
};

Resources