Hi I have a sectionList that is passed an array of colors + background imgs that are chosen at random to render as a background of each row item. When I swipe to access that view the colors flicker for a few seconds as the random selection is still occurring. Each time I return to the screen with the list, the colors will flicker for a few seconds then settle. how can I have no flickering and the random selection of color happen once at load?
class Main extends React.Component {
constructor(props, context) {
super(props, context);
// app state
this.state = {
listColor: [
['rgba(0,36,155,0.8)', 'rgba(26,0,87,0.8)'],
['rgba(155,0,0,0.8)', 'rgba(87,0,0,0.8)']],
}
}
_handleRandomIndex(arr) {
return arr[Math.floor(Math.random() * arr.length)]
}
_renderItem = ({item, section}) => (
<TouchableScale
style={styles.row}
onPress={this._onRowPress.bind(this, item)}
activeScale={0.94}
tension={0}
friction={3}
>
<View style={ styles.elevationLow } borderRadius={9} >
<ImageBackground source={{uri: this._handleRandomIndex(item.bgImgs).image_link }} borderRadius={9} style={ styles.imageBackground }>
<LinearGradient
colors={ this._handleRandomIndex(this.state.listColor) }
start={[0.1,0.1]}
end={[0.5,0.5]}
style={{ padding: 20, borderRadius: 9 }}>
</LinearGradient>
</ImageBackground>
</View>
}
</TouchableScale>
)
}
Because you are doing a Math.random every re-render. So whenever the render function calls, it is changing the color.
Change to this:
function _handleRandomIndex(arr) {
return arr[Math.floor(Math.random() * arr.length)]
}
class Main extends React.Component {
state = {
listColor: [
['rgba(0,36,155,0.8)', 'rgba(26,0,87,0.8)'],
['rgba(155,0,0,0.8)', 'rgba(87,0,0,0.8)']
]
}
_renderItem = ({ item, section }) => <Item item={item} listColor={this.state.listColor} />
}
class Item extends Component {
rando = _handleRandomIndex(this.props.listColor);
render() {
const { item } = this.props;
return (
<TouchableScale
style={styles.row}
onPress={this._onRowPress.bind(this, item)}
activeScale={0.94}
tension={0}
friction={3}
>
<View style={styles.elevationLow} borderRadius={9}>
<ImageBackground source={{ uri: this._handleRandomIndex(item.bgImgs).image_link }} borderRadius={9} style={styles.imageBackground}>
<LinearGradient
colors={this.rando}
start={[0.1, 0.1]}
end={[0.5, 0.5]}
style={{ padding: 20, borderRadius: 9 }}>
</LinearGradient>
</ImageBackground>
</View>
</TouchableScale>
)
}
}
Noitidart's answer will work but all the items will be randomized to same color, if you want each item a different color I think you need to do this:
_renderItem = ({item, section}) => {
const color = this._handleRandomIndex(this.state.listColor);
return (
<TouchableScale
style={styles.row}
onPress={this._onRowPress.bind(this, item)}
activeScale={0.94}
tension={0}
friction={3}
>
<View style={ styles.elevationLow } borderRadius={9} >
<ImageBackground source={{uri: this._handleRandomIndex(item.bgImgs).image_link }} borderRadius={9} style={ styles.imageBackground }>
<LinearGradient
colors={ color }
start={[0.1,0.1]}
end={[0.5,0.5]}
style={{ padding: 20, borderRadius: 9 }}>
</LinearGradient>
</ImageBackground>
</View>
}
</TouchableScale>
)
}
Related
Please tell me that
if I want to change the CustomExample Class component into a functional component
**as: ** const CustomExample = () =>{...}
then how will change the following code to work in similar manner:
<CustomPicker
placeholder={'Please select your favorite item...'}
options={options}
getLabel={item => item.label}
fieldTemplate={this.renderField}
optionTemplate={this.renderOption}
/>
I have tried following methods:
changing definition as
rederField(settings){...} to const renderField = (settings) => {...}
and then assigning renderField to fieldTemplate as follow:
* fieldTemplate={renderField()}
* fieldTemplate={()=>renderField()}
* fieldTemplate={renderField(selectedItem,defaultText,getLabel,clear)}
on each attempt it showed some error.
PLZ HELP ME I'M STUCK ON IT FROM LAST FEW DAYS
GOING THROUGH ALL THE DOCS WILL TAKE MONTHS FOR ME.
import * as React from 'react'
import { Alert, Text, View, TouchableOpacity, StyleSheet } from 'react-native'
import { CustomPicker } from 'react-native-custom-picker'
export class CustomExample extends React.Component {
render() {
const options = [
{
color: '#2660A4',
label: 'One',
value: 1
},
{
color: '#FF6B35',
label: 'Two',
value: 2
},
]
return (
<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center' }}>
<CustomPicker
placeholder={'Please select your favorite item...'}
options={options}
getLabel={item => item.label}
fieldTemplate={this.renderField}
optionTemplate={this.renderOption}
/>
</View>
)
}
renderField(settings) {
const { selectedItem, defaultText, getLabel, clear } = settings
return (
<View style={styles.container}>
<View>
{!selectedItem && <Text style={[styles.text, { color: 'grey' }]}>{defaultText}</Text>}
{selectedItem && (
<View style={styles.innerContainer}>
<TouchableOpacity style={styles.clearButton} onPress={clear}>
<Text style={{ color: '#fff' }}>Clear</Text>
</TouchableOpacity>
<Text style={[styles.text, { color: selectedItem.color }]}>
{getLabel(selectedItem)}
</Text>
</View>
)}
</View>
</View>
)
}
renderOption(settings) {
const { item, getLabel } = settings
return (
<View style={styles.optionContainer}>
<View style={styles.innerContainer}>
<View style={[styles.box, { backgroundColor: item.color }]} />
<Text style={{ color: item.color, alignSelf: 'flex-start' }}>{getLabel(item)}</Text>
</View>
</View>
)
}
}
// STYLE FILES PRESENT HERE.
change the definition of function to
function renderOption(settings) {...}
function renderField (settings) {...}
and call function like this.
<CustomPicker
placeholder={'Please select your favorite item...'}
options={options}
getLabel={item => item.label}
fieldTemplate={renderField}
optionTemplate={renderOption}
/>
Here, I am fetching data from firebase and then trying to output it in a tinder card like format. My code is as follows -
import React from 'react';
import { View, ImageBackground, Text, Image, TouchableOpacity } from 'react-native';
import CardStack, { Card } from 'react-native-card-stack-swiper';
import City from '../components/City';
import Filters from '../components/Filters';
import CardItem from '../components/CardItem';
import styles from '../assets/styles';
import Demo from '../assets/demo';;
import {db} from '../config/config';
class Home extends React.Component {
constructor (props) {
super(props);
this.state = ({
items: [],
isReady: false,
});
}
componentWillMount() {
let items = [];
db.ref('cards').once('value', (snap) => {
snap.forEach((child) => {
let item = child.val();
item.id = child.key;
items.push({
name: child.val().pet_name,
description: child.val().pet_gender,
pet_age: child.val().pet_age,
pet_breed: child.val().pet_breed,
photoUrl: child.val().photoUrl,
});
});
//console.log(items)
this.setState({ items: items, isReady: true });
console.log(items);
});
}
componentWillUnmount() {
// fix Warning: Can't perform a React state update on an unmounted component
this.setState = (state,callback)=>{
return;
};
}
render() {
return (
<ImageBackground
source={require('../assets/images/bg.png')}
style={styles.bg}
>
<View style={styles.containerHome}>
<View style={styles.top}>
<City />
<Filters />
</View>
<CardStack
loop={true}
verticalSwipe={false}
renderNoMoreCards={() => null}
ref={swiper => {
this.swiper = swiper
}}
>
{this.state.items.map((item, index) => (
<Card key={index}>
<CardItem
//image={item.image}
name={item.name}
description={item.description}
actions
onPressLeft={() => this.swiper.swipeLeft()}
onPressRight={() => this.swiper.swipeRight()}
/>
</Card>
))}
</CardStack>
</View>
</ImageBackground>
);
}
}
export default Home;
I am fetching data and storing it in an array called items[]. Console.log(items) gives me the following result:
Array [
Object {
"description": "male",
"name": "dawn",
"pet_age": "11",
"pet_breed": "golden retriever",
"photoUrl": "picture",
},
Object {
"description": "Male",
"name": "Rambo",
"pet_age": "7",
"pet_breed": "German",
"photoUrl": "https://firebasestorage.googleapis.com/v0/b/woofmatix-50f11.appspot.com/o/pFkdnwKltNVAhC6IQMeSapN0dOp2?alt=media&token=36087dae-f50d-4f1d-9bf6-572fdaac8481",
},
]
Furthermore, I want to output my data in a card like outlook so I made a custom component called CardItem:
import React from 'react';
import styles from '../assets/styles';
import { Text, View, Image, Dimensions, TouchableOpacity } from 'react-native';
import Icon from './Icon';
const CardItem = ({
actions,
description,
image,
matches,
name,
pet_name,
pet_gender,
pet_age,
onPressLeft,
onPressRight,
status,
variant
}) => {
// Custom styling
const fullWidth = Dimensions.get('window').width;
const imageStyle = [
{
borderRadius: 8,
width: variant ? fullWidth / 2 - 30 : fullWidth - 80,
height: variant ? 170 : 350,
margin: variant ? 0 : 20
}
];
const nameStyle = [
{
paddingTop: variant ? 10 : 15,
paddingBottom: variant ? 5 : 7,
color: '#363636',
fontSize: variant ? 15 : 30
}
];
return (
<View style={styles.containerCardItem}>
{/* IMAGE */}
<Image source={image} style={imageStyle} />
{/* MATCHES */}
{matches && (
<View style={styles.matchesCardItem}>
<Text style={styles.matchesTextCardItem}>
<Icon name="heart" /> {matches}% Match!
</Text>
</View>
)}
{/* NAME */}
<Text style={nameStyle}>{name}</Text>
{/* DESCRIPTION */}
{description && (
<Text style={styles.descriptionCardItem}>{description}</Text>
)}
{/* STATUS */}
{status && (
<View style={styles.status}>
<View style={status === 'Online' ? styles.online : styles.offline} />
<Text style={styles.statusText}>{pet_age}</Text>
</View>
)}
{/* ACTIONS */}
{actions && (
<View style={styles.actionsCardItem}>
<View style={styles.buttonContainer}>
<TouchableOpacity style={[styles.button, styles.red]} onPress={() => {
this.swiper.swipeLeft();
}}>
<Image source={require('../assets/red.png')} resizeMode={'contain'} style={{ height: 62, width: 62 }} />
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.orange]} onPress={() => {
this.swiper.goBackFromLeft();
}}>
<Image source={require('../assets/back.png')} resizeMode={'contain'} style={{ height: 32, width: 32, borderRadius: 5 }} />
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.green]} onPress={() => {
this.swiper.swipeRight();
}}>
<Image source={require('../assets/green.png')} resizeMode={'contain'} style={{ height: 62, width: 62 }} />
</TouchableOpacity>
</View>
</View>
)}
</View>
);
};
export default CardItem;
The problem is when I try to pass the data in my items[] array, the cardItem component just doesnt work. To dry-run, I used a sample demo array and when I use the Demo array, my component works just fine. What am I doing wrong? I have been tinkering with this problem for quite a while now. Any help whatsoever would be appreciated.
I want a + button at the end of all images, in case 1 there should be only this 1 button on-screen if no image is available and else after the available images this button would be on last of all images, but I want to make this button look same as these images and also in row of 3
My code for the flat list is as below.
<FlatList
numColumns={3}
data={this.state.images}
renderItem={({ item }) => <SafeAreaView style={{ flex: 1, alignItems: 'center' }}>
<Image style={{ margin: 5, height: 120, width: 120 }}
source={{ uri:'data:image/png;base64,' + item.image }} />
</SafeAreaView>}
keyExtractor={item => item.id}
/>
You can put the + in a span whose position is absolute and wrap the last image in it. There's more styling to do here, but this is the start.
The function that adds the image should remove the span wrapper from the old last image and add it to the new one
<FlatList
numColumns={3}
data={this.state.images}
renderItem={({ item }) => <SafeAreaView style={{ flex: 1, alignItems: 'center' }}>
{(item.index + 1) % 3 == 0 ?
<TouchableOpacity onPress={() => { }}><Image style={{ margin: 5, height: 120, width: 120 }}
source={{ uri: 'data:image/png;base64,' + item.image }} />
{/* you can put your + icon image here */}
</TouchableOpacity>
:
<Image style={{ margin: 5, height: 120, width: 120 }}
source={{ uri: 'data:image/png;base64,' + item.image }} />
}
</SafeAreaView>}
keyExtractor={item => item.id}
/>
You just need to conditionally render the FlatList and add the button on the same "row" as the images.
I want to make this button look same as these images
Styling is up to you :)
Here's a little demo how it would work.
import React, { Component } from "react";
import {
Button,
StyleSheet,
Text,
View,
FlatList,
SafeAreaView
} from "react-native";
const data = [{ name: "first" }, { name: "second" }, { name: "third" }];
class App extends Component {
renderFlatList() {
const Item = ({ title }) => {
return (
<SafeAreaView style={styles.listItem}>
<Text style={{ padding: 10 }}>{title}</Text>
</SafeAreaView>
);
};
return (
<View>
<FlatList
numColumns={3}
data={data}
renderItem={({ item }) => ( <Item title={item.name} />)}
keyExtractor={item => item.id}
/>
</View>
);
}
render() {
return (
<View style={styles.container}>
{/* You probably are using state or props for the data, so this checking is just for the demo */}
{typeof data !== "undefined" && data.length > 0 && this.renderFlatList()}
<View>
{/* You could use <TouchableHighlight /> or whatever suits your needs*/}
<Button title={"+"} />
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: "row"
},
listItem: {
backgroundColor: "gold",
}
});
export default App;
The goal is to pass the State of the Photos from my CameraRoll.js (Modal) to EventCreator.js(Modal) without using the React Redux. I'm using React Native Navigation V1.
I'm wondering maybe it is possible state of photos: [] become props? Just don't know how to do it. Need help, thank you guys!
Here are my codes:
CameraRoll.js:
state = {
photos: [],
index: null,
pickedImage: null
}
getPhotos = () => {
CameraRoll.getPhotos({
first: 200,
assetType: 'All'
})
.then(res => {
this.setState({
photos: res.edges,
});
})
.catch((err) => {
console.log('Error image: ' + err);
});
};
render() {
return(
<View style={styles.container}>
<Image source={{uri: this.state.pickedImage}} style={styles.image}/>
<ScrollView contentContainerStyle={styles.scrollView} showsVerticalScrollIndicator={false}>
{this.state.photos.map((photos, index) => {
return(
<TouchableHighlight
style={{opacity: index === this.state.index ? .5 : 1}}
onPress={() => this.setState({pickedImage: photos.node.image.uri})}
key={index}
underlayColor='transparent'
>
<Image
style={{width: width / 3, height: width /3}}
source={{uri: photos.node.image.uri}}
resizeMode='cover'
/>
</TouchableHighlight>
);
})}
</ScrollView>
</View>
);
}
EventCreator.js:
render(){
return(
<View style={styles.container}>
<EventInput
titleOnChangeText={this.eventNameChangedHandler}
descriptionOnChangeText={this.eventDescriptionChangedHandler}
titleEvent={this.state.controls.eventName}
descriptionEvent={this.state.controls.eventDescription}
/>
<Image
style={styles.image}
source={"I want to pass the image here from CameraRoll.js"}
resizeMode='contain'
/>
</View>
);
}
if you mean this:
onPress={() => this.setState({pickedImage: photos.node.image.uri})}
it just change the state value. What you should do is put an if statement on the return of cameraRoll.js:
private onPress = (img) => {
this.props.onImagePicked(img)
}
render() {
return(
<View style={styles.container}>
<Image source={{uri: this.state.pickedImage}} style={styles.image}/>
<ScrollView contentContainerStyle={styles.scrollView} showsVerticalScrollIndicator={false}>
{this.state.photos.map((photos, index) => {
return(
<TouchableHighlight
style={{opacity: index === this.state.index ? .5 : 1}}
onPress={() => this.onPress(photos.node.image.uri))}
key={index}
underlayColor='transparent'
>
<Image
style={{width: width / 3, height: width /3}}
source={{uri: photos.node.image.uri}}
resizeMode='cover'
/>
</TouchableHighlight>
);
})}
</ScrollView>
</View>
);
}
And in EventCreator.js:
constructor(){
super(props);
this.state = {
pickedImg: undefined
}
}
private onImagePicked = (newImg) => {
this.setState({
pickedImg: newImg
})
}
render(){
return(
<View style={styles.container}>
<EventInput
titleOnChangeText={this.eventNameChangedHandler}
descriptionOnChangeText={this.eventDescriptionChangedHandler}
titleEvent={this.state.controls.eventName}
descriptionEvent={this.state.controls.eventDescription}
/>
<Image
style={styles.image}
source={this.props.source}
resizeMode='contain'
/>
<CameraRoll props={...} onImagePicked={this.onImagePicked}/>
</View>
);
}
The data i sent it from fetch and php , it's can be load and the result of the flat liste is none and it was only the text i wrote also i use flatliste but nothing in on the screen , i think the problem is in array sat and how to use value , key and item
import ajax from './fetchdata.js'
export class Home extends Component {
constructor(props) {
super(props);
this.state = { sat: [] };
}
async componentDidMount() {
const sat = await ajax.fetchset();
console.log(this.state.sat);
this.setState({sat});
}
render() {
return (
<View style={styles.container}>
<Text style={styles.h2text}>
Black Order
</Text>
<FlatList
data={this.state.sat}
keyExtractor={item => item.idC}
renderItem={ ({item}) => {
return (
<View style={{ flex : 1, flexDirection : "row" }}>
<View style={{ flex : .6 }}>
<Text style={{ fontSize : 20 , textColor:'red'}}>{item.nom}</Text>
</View>
<View style={{ flex : .4 }}>
<Text style={{ fontSize : 20 , textColor:'red' }}>{item.adresse} points</Text>
</View>
</View>
);
}
}
/>
</View>
);
}
}
*/
export default Home;
////////fetchdata.js
export default {
async fetchset() {
try {
let response = await fetch('http://localhost/APP/Chauffeur/Backendapp/api/Traitement/AffichageStation.php');
let responseJsonData = await response.json();
console.log("done")
return responseJsonData;
}
catch(e) {
console.log(e)
}
}
}
exepected a liste of data the adresse and nom , but the message is only the the text Black Order