I am trying to create an app using react native. Im using expo.
I ve a component named DistList, which should be repeatedly called based on the number of entries from an object. But, the component is not called when used inside a forEach
HomeData.js
import React from 'react';
import { StyleSheet, Text, View, SafeAreaView, Platform, StatusBar, ScrollView, Dimensions } from 'react-native';
import dataCovid from '../store/dataCovid.json'
import DataList from './DataList.js'
import colors from './config/colors.js'
export default class HomeData extends React.Component{
constructor(props) {
super(props);
this.state = {
dataSource : '',
currentTotal : 0,
currentRecovered : 0,
currentDecreased : 0,
currentActive : 0,
}
}
fetchUsers(){
fetch("https://api.covidindiatracker.com/state_data.json")
.then(response => response.json())
.then((responseJson)=> {
this.setState({
loading: false,
dataSource: responseJson
})
})
.catch(error=>console.log(error)) //to catch the errors if any
// console.log(responseJson)
// this.calculateCount();
}
componentDidMount(){
this.fetchUsers();
}
/* componentDidUpdate(){
this.calculateCount();
} */
calculateCount(){
console.log("cc")
// console.log("cclen", this.state.dataSource)
// console.log("cclen", this.state.dataSource.length)
if(this.state.dataSource.length > 0){
let data = /* JSON.stringify( */this.state.dataSource;
// console.log(data)
// if(recoveredResult == 0||decreasedResult == 0||activeResult == 0){
console.log("inside")
// var dataValue = Array.from(data)
// var activeResult = data.map(activeVal => activeVal.active).reduce((nextValue, activeVal) => activeVal + nextValue);
var recoveredResult = data.map(activeVal => activeVal.recovered).reduce((nextValue, activeVal) => activeVal + nextValue);
var decreasedResult = data.map(activeVal => activeVal.deaths).reduce((nextValue, activeVal) => activeVal + nextValue);
var activeResult = data.map(activeVal => activeVal.active).reduce((nextValue, activeVal) => activeVal + nextValue);
var totalResult = recoveredResult+decreasedResult+activeResult;
console.log(recoveredResult)
console.log(decreasedResult)
console.log(activeResult)
this.setState({
currentTotal : totalResult,
currentRecovered : recoveredResult,
currentDecreased : decreasedResult,
currentActive : activeResult,
})
// }
console.log(recoveredResult)
console.log(this.state.currentRecovered)
console.log(this.state.currentDecreased)
console.log(this.state.currentActive)
}
}
handleDataList=()=>{
console.log("asdasd", this.state.dataSource.length)
if(this.state.dataSource.length > 0){
this.state.dataSource.forEach(function(element){
console.log(element);
return (
<View>
<DataList
state={element.state}
recovered={element.recovered}
decreased={element.deaths}
total= {element.confirmed+element.recovered+element.deaths+element.active}
heading={true}
/>
</View>
);
});
}
}
render() {
// console.log("erer", this.state.dataSource)
// console.log("erer", this.state.currentRecovered)
// console.log("erer", JSON.stringify(dataCovid) )
if(this.state.currentActive == 0){
this.calculateCount();
}
return (
<View style={styles.container}>
{/* <ScrollView> */}
<View style={styles.containerTop}>
<View style={styles.totalContainerOne}>
<Text style={[styles.textStyle, styles.textTotal, ]}>Total</Text>
<Text>[{this.state.currentTotal}]</Text>
</View>
<View style={styles.totalContainerTwo}>
<View style={styles.recoveredContainer}>
<Text style={[styles.textStyle, styles.textRecovered, ]}>Recovered</Text>
<Text>[{this.state.currentRecovered}]</Text>
</View>
<View style={styles.decreasedContainer}>
<Text style={[styles.textStyle, styles.textDecreased, ]}>Decreased</Text>
<Text>[{this.state.currentDecreased}]</Text>
</View>
<View style={styles.activeContainer}>
<Text style={[styles.textStyle, styles.textActive, ]}>Active</Text>
<Text>[{this.state.currentActive}]</Text>
</View>
</View>
</View>
<View style={styles.containerBottom}>
<DataList state="State" total="Total" recovered="Recovered" decreased="Decreased" heading={true}/>
<DataList state="State" total="Total" recovered="Recovered" decreased="Decreased" heading={true}/>
{
this.handleDataList()
}
</View>
{/* </ScrollView> */}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
// width : '100%',
// flex: 1,
// height : '100%',
// height: 1500,
// flexDirection : 'row',
// backgroundColor: 'blue',
// alignItems: 'center',
// justifyContent: 'space-evenly',
// marginTop : Platform.OS === 'android' ? StatusBar.currentHeight : 0,
// elevation : 5
},
containerTop: {
// flex: 0.3,
// height : '15%',
height: Dimensions.get('window').height/3,
// flexDirection : 'row',
// backgroundColor: 'blue',
alignItems: 'center',
justifyContent: 'space-evenly',
// marginTop : Platform.OS === 'android' ? StatusBar.currentHeight : 0,
// elevation : 5
},
totalContainerOne: {
height : '45%',
// flex: 0.8,
width : '90%',
backgroundColor: '#eeeeee',
elevation : 20,
alignItems: 'center',
justifyContent: 'center',
borderRadius : 15,
},
textTotal:{
color : colors.totalColor,
},
totalContainerTwo: {
// flex: 0.8,
width : '100%',
height : '45%',
// backgroundColor: 'green',
flexDirection : 'row',
justifyContent : 'space-evenly'
},
recoveredContainer: {
// flex: 1,
width : '30%',
// height : '45%',
backgroundColor: '#eeeeee',
elevation : 50,
alignItems: 'center',
justifyContent: 'center',
borderRadius : 15,
},
textRecovered:{
color : colors.recoveredColor,
},
decreasedContainer: {
// flex: 1,
width : '30%',
// height : '45%',
backgroundColor: '#eeeeee',
elevation : 50,
alignItems: 'center',
justifyContent: 'center',
borderRadius : 15,
},
textDecreased:{
color : colors.decreasedColor,
},
activeContainer: {
// flex: 1,
width : '30%',
// height : '45%',
backgroundColor: '#eeeeee',
elevation : 50,
alignItems: 'center',
justifyContent: 'center',
borderRadius : 15,
},
textActive:{
color : colors.activeColor,
},
textStyle:{
fontSize : 18,
fontWeight : '700',
},
containerBottom: {
paddingTop : 10,
// flex: 0.4,
// height:'85%',
// flexDirection : 'row',
// backgroundColor: 'blue',
alignItems: 'center',
justifyContent: 'space-evenly',
// marginTop : Platform.OS === 'android' ? StatusBar.currentHeight : 0,
// elevation : 5
},
});
DataList.js
import React from 'react';
import { StyleSheet, Text, View, SafeAreaView, Platform, StatusBar, ScrollView, Dimensions } from 'react-native';
import dataCovid from '../store/dataCovid.json'
import colors from './config/colors.js'
export default class DataList extends React.Component{
constructor(props) {
super(props);
this.state = {
}
}
render() {
const {state, total, recovered, decreased, heading} = this.props;
const testStyle = (heading)? styles.testHeadingStyle : styles.dataStyle
return (
<View style={styles.container}>
<View style={styles.stateBox}>
<Text style={testStyle}>{state}</Text>
</View>
<View style={styles.stateBox}>
<Text style={testStyle}>{total}</Text>
</View>
<View style={styles.stateBox}>
<Text style={testStyle}>{recovered}</Text>
</View>
<View style={styles.stateBox}>
<Text style={testStyle}>{decreased}</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
width : '100%',
flex: 1,
// height : '100%',
// height: 1500,
flexDirection : 'row',
// backgroundColor: 'blue',
alignItems: 'center',
justifyContent: 'space-evenly',
// marginTop : Platform.OS === 'android' ? StatusBar.currentHeight : 0,
// elevation : 5
},
stateBox:{
height : 30,
width : 87,
backgroundColor : '#f6f6f7',
borderRadius : 5,
// top : 5,
justifyContent : 'center',
// alignItems : 'center',
elevation : 5,
textAlign : 'left',
paddingLeft : 5,
},
testHeadingStyle:{
fontSize : 15,
fontWeight : '700',
color : '#6c757d',
textShadowColor: 'rgba(0, 0, 0, 0.50)',
textShadowOffset: {width: -1, height: 1},
textShadowRadius: 10,
},
dataStyle:{
fontSize : 15,
fontWeight : '700',
color : '#6c757d',
// textShadowColor: 'rgba(0, 0, 0, 0.50)',
// textShadowOffset: {width: -1, height: 1},
// textShadowRadius: 10,
}
});
I am using this function handleDataList() to call the DistList.js component in forEach. But calling component is not working here. Can someone assist please.
{
this.handleDataList()
}
You can do this, a function inside a render, and it will render whatever the function will return, which can be some html snippet or a component.
However you need to make sure that handleDataList() returns something
handleDataList=()=>{
console.log("asdasd", this.state.dataSource.length)
if(this.state.dataSource.length > 0){
this.state.dataSource.forEach(function(element){
console.log(element);
return (
<View>
<DataList
state={element.state}
recovered={element.recovered}
decreased={element.deaths}
total= {element.confirmed+element.recovered+element.deaths+element.active}
heading={true}
/>
</View>
);
});
}
}
this will return undefined.
You may think it will return
return (
<View>
<DataList
state={element.state}
recovered={element.recovered}
decreased={element.deaths}
total= {element.confirmed+element.recovered+element.deaths+element.active}
heading={true}
/>
</View>
);
but it doesn't, because this return is the return of the forEach function callback, but that's not going to affect handleDataList at all.
handleDataList=()=>{
console.log("asdasd", this.state.dataSource.length)
if(this.state.dataSource.length > 0){
return this.state.dataSource.map(function(element){
console.log(element);
return (
<View>
<DataList
state={element.state}
recovered={element.recovered}
decreased={element.deaths}
total= {element.confirmed+element.recovered+element.deaths+element.active}
heading={true}
/>
</View>
);
});
}
}
should return.
Related
I am creating a react native app on snack expo.
The app allows the user to select image from device on screen one (PhotoSelection.js) and shows the image to screen 2 (FrameSelection.js). Upon selecting an image from device, I am receiving this error:
NoSuchKeyThe specified key does not exist.v2/46/FrameSelectionM0EK0RMAJZ9JH00KGQ3jUVOsp2fXZp3ZWPaMeUjM57WUcEEUGHNvluc/kOn1FcOfRMnlOquUUUZVYGaB/d2cQQNh0Ko=
Screen 1 (PhotoSelection.js):
import React from 'react';
import { StatusBar } from 'expo-status-bar';
import { Text, View, StyleSheet, Image, TouchableOpacity, Button} from 'react-native';
import MyCustomFont from '../assets/Poppins-Bold.ttf';
import { useNavigation } from '#react-navigation/native';
import * as ImagePicker from 'expo-image-picker';
import { Constants } from 'expo-constants';
export const PhotoSelection =() =>{
const handleSelectImage = async () => {
try {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
});
if (!result.cancelled) {
navigation.navigate('FrameSelection', { image: result.uri });
}
} catch (error) {
console.log(error);
}
};
return (
<View style ={styles.container}>
<View>
<Image
style = {styles.img1}
source={require('../assets/image 1.png')}
/>
</View>
<View>
<Image
style = {styles.img2}
source ={require('../assets/Group 546020456.png')}
/>
</View>
<Text style={styles.text}>
Frame your special photos & share it with your friends
</Text>
<TouchableOpacity style ={styles.touchbutton}
onPress={handleSelectImage}
>
SELECT PHOTO
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex:1,
backgroundColor: '#603FC0',
justifyContent: 'center',
alignItems:'center',
width:'100%'
},
img1:{
width:360,
resizeMode:'cover'
},
img2:{
"width":220,
marginTop:50
},
text: {
"width": 200,
"fontFamily": 'MyCustomFont',
"fontStyle": "normal",
"fontWeight": "500",
"fontSize": 16,
"lineHeight": 24,
"textAlign": "center",
},
touchbutton:{
marginTop: 30,
paddingLeft:40,
paddingRight:40,
borderRadius:8,
paddingTop:16,
paddingBottom:16,
alignSelf:'center',
backgroundColor:'white',
fontFamily: 'MyCustomFont',
fontStyle: 'normal',
fontWeight: 700,
fontSize: 16,
},
});
Screen 2 (FrameSelection.js):
import React, {useState} from 'react';
import { Text, View, StyleSheet, Image, TouchableOpacity} from 'react-native';
import {PhotoSelection} from './PhotoSelection';
import { Constants } from 'expo-constants';
export const FrameSelection =({route}) =>{
const frames =
[
{ id: 1, small: require('../assets/image 4.png'), large: require('../assets/image 4.png') },
{ id: 2, small: require('../assets/image 4.png'), large: require('../assets/image 4.png') },
{ id: 3, small: require('../assets/image 4.png'), large: require('../assets/image 4.png') },
];
const [selectedFrame, setSelectedFrame] = useState(frames[0]);
const handleImagePress = (frame) => {
setSelectedFrame(frame);
};
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
{route.params.image ? (
<Image source={{ uri: route.params.image }} style={{position: 'absolute', padding:0, top: 0, left: 0, width: '100%', height: '100%', resizeMode: 'contain', backgroundColor: 'white', zIndex: 1} } />
) : (
<Text>No image selected</Text>
)}
<Image
source={selectedFrame.large}
style={{flex:1,position: 'absolute', resizeMode: 'contain', top: 0, left: 0, width: '100%', height: '100%', zIndex: 2}}
resizeMode="contain" />
</View>
<View style={{ flexDirection: 'row', height: 100 }}>
{frames.map((frame) => (
<TouchableOpacity onPress={() => handleImagePress(frame)}>
<Image source={frame.small} style={{ width: 60, height: 60, margin: 10 }} resizeMode="contain" />
</TouchableOpacity>
))}
</View>
</View>
);
};
I Tried checking if the selected image's uri is being passed correctly.
I am new to React Native, I tried to create a component for my radio button but I encountered some issue with the Style when I added the elevation, and it is adding the shadow inside the View instead of outside of the View
Here is my code
import {Text, View, StyleSheet} from 'react-native';
import {RadioButton} from 'react-native-paper';
import {
ScrollView,
TextInput,
TouchableOpacity,
} from "react-native-gesture-handler";
function Chosen({values, onChange, defaultIndex, selectedIndexAtt, renderComponent}){
const [index, setIndex] = useState(defaultIndex ? defaultIndex : 0);
const getRadioStatus = (itemIndex) => {
return index == itemIndex ? 'checked' : 'unchecked';
}
const handleRadioPress = (itemIndex) => {
setIndex(itemIndex);
onChange(itemIndex);
}
return(
<ScrollView style={styles.container}>
<View style={styles.containerRow}>
{values.map((item, index)=> {
return (<View style={styles.itemContainer}>
<View style={styles.item}>
{renderComponent(item)}
<View style={styles.radioButton}>
<RadioButton value={item[selectedIndexAtt ? selectedIndexAtt : index]}
status={getRadioStatus(item[selectedIndexAtt ? selectedIndexAtt : index])}
onPress={() => {
handleRadioPress(item[selectedIndexAtt ? selectedIndexAtt : index])
}}/>
</View>
</View>
</View>)
})}
</View>
</ScrollView>
);
}
const styles = StyleSheet.create({
container:{
flexDirection: 'column',
flex: 1
},
containerRow:{
flexDirection: 'row',
flexWrap: 'wrap',
},
itemContainer: {
width: "50%",
padding: 1
},
item: {
flexDirection: 'row',
margin: 10,
borderWidth: 1,
borderColor: 'rgba(105,105,105,0.6)',
borderRadius: 15,
elevation: 0.1
},
radioButton: {
justifyContent: 'center',
flex: 1,
alignItems: 'flex-end'
}
});
export default Chosen;
and here is how I call it from the parent
<Chosen values={dummyData} defaultIndex={dummyData[0].id} selectedIndexAtt='id' renderComponent={(item) => {
return (
<View>
<Text>{item.name}</Text>
</View>
)
}} onChange={onChange}></Chosen>
and the result is this:
elevation shadow issue
Can someone please help me with this?
You have to provide this for a shadow in react native. Change the values according to your need.
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 10,
},
shadowOpacity: 0.5,
shadowRadius: 10,
elevation: 20,
I get an error for to many re-renders. It seems that the compareDate function gets run every time a state updates. The compareDate only has to be run when the app opens to check if it's a new day since last login so that it can reset the program by doing addWater(-dailyGoal). Does anyone know how I can make it only run once on opening the app?
import { StatusBar } from 'expo-status-bar';
import React, { useState } from 'react';
import {
StyleSheet,
Text,
View,
SafeAreaView,
Alert,
TouchableOpacity,
Keyboard,
TextInput,
} from 'react-native';
import AsyncStorage from '#react-native-community/async-storage';
import { FontAwesomeIcon } from '#fortawesome/react-native-fontawesome';
import { faTint, faCog, faTimes } from '#fortawesome/free-solid-svg-icons';
export default function App() {
// set vars
const [waterDrank, setWaterDrank] = useState(0);
const [menuOpen, setmenuOpen] = useState(false);
const [dailyGoal, setDailyGoal] = useState(3700);
const [bottle, setBottle] = useState(250);
const [dailyGoalSettings, onChangeDailyGoalSettings] = useState(
`${dailyGoal}`
);
const [bottleSettings, onChangeBottleSettings] = useState(`${bottle}`);
// Async storage
const storeWater = async (value) => {
try {
await AsyncStorage.setItem('storedWater', value);
} catch (e) {
// saving error
}
};
const getStoredWater = async () => {
try {
const value = await AsyncStorage.getItem('storedWater');
if (value !== null && !isNaN(value)) {
setWaterDrank(parseInt(value));
}
} catch (e) {
// error reading value
}
};
// init stored water data
getStoredWater();
// store settings
const storeSettings = async (daily, bottle) => {
try {
await AsyncStorage.setItem('dailyGoalSetting', daily);
await AsyncStorage.setItem('bottleSetting', bottle);
} catch (e) {
// saving error
}
};
const getStoredSettings = async () => {
try {
const valueDailyGoalSetting = await AsyncStorage.getItem(
'dailyGoalSetting'
);
const valueBottleSetting = await AsyncStorage.getItem(
'bottleSetting'
);
if (
valueDailyGoalSetting !== null &&
!isNaN(valueDailyGoalSetting) &&
valueBottleSetting !== null &&
!isNaN(valueBottleSetting)
) {
setDailyGoal(valueDailyGoalSetting);
setBottle(valueBottleSetting);
}
} catch (e) {
// error reading value
}
};
// init stored settings data
getStoredSettings();
const addWater = (amount) => {
amount = parseInt(amount);
if (!isNaN(amount)) {
if (waterDrank + amount >= dailyGoal) {
setWaterDrank(dailyGoal);
storeWater(`${dailyGoal}`);
} else if (waterDrank + amount <= 0) {
setWaterDrank(0);
storeWater(`0`);
} else {
setWaterDrank(waterDrank + amount);
storeWater(`${waterDrank + amount}`);
}
} else {
setWaterDrank(waterDrank + 0);
storeWater(`${waterDrank + 0}`);
}
};
const compareDate = () => {
const firstDateIsPastDayComparedToSecond = (firstDate, secondDate) =>
firstDate.setHours(0, 0, 0, 0) - secondDate.setHours(0, 0, 0, 0) <
0;
const currentDate = new Date();
const storedDate = new Date(currentDate);
storedDate.setDate(storedDate.getDate() - 1);
// is the first date in the past
if (firstDateIsPastDayComparedToSecond(storedDate, currentDate)) {
addWater(-dailyGoal);
}
};
compareDate();
const settingsToggle = () => {
setmenuOpen(!menuOpen);
Keyboard.dismiss();
};
const settingsSave = () => {
storeSettings(dailyGoalSettings, bottleSettings);
getStoredSettings();
settingsToggle();
};
return (
<View style={styles.body}>
{/* settings */}
<View
style={[
styles.settingsMenu,
{
display: `${menuOpen ? 'block' : 'none'}`,
},
]}
>
<SafeAreaView onPress={() => Keyboard.dismiss()}>
<TouchableOpacity
style={styles.settingsButton}
onPress={() => settingsToggle()}
>
<FontAwesomeIcon
icon={faTimes}
color={'black'}
size={24}
/>
</TouchableOpacity>
<View style={{ paddingHorizontal: 20 }}>
<Text style={styles.settingsText}>
Daily water goal in ml
</Text>
<TextInput
style={styles.settingsInput}
onChangeText={(text) =>
onChangeDailyGoalSettings(text)
}
value={dailyGoalSettings}
keyboardType={'number-pad'}
/>
<Text style={styles.settingsText}>
Amount of a bottle in ml
</Text>
<TextInput
style={styles.settingsInput}
onChangeText={(text) =>
onChangeBottleSettings(text)
}
value={bottleSettings}
keyboardType={'number-pad'}
/>
<TouchableOpacity
style={styles.settingsSave}
onPress={() => settingsSave()}
>
<Text
style={{
alignSelf: 'center',
color: '#fff',
fontWeight: 'bold',
}}
>
Save
</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
</View>
{/* main content */}
<SafeAreaView style={styles.container}>
<TouchableOpacity
style={styles.settingsButton}
onPress={() => settingsToggle()}
>
<FontAwesomeIcon icon={faCog} color={'white'} size={24} />
</TouchableOpacity>
<View style={styles.wrapper}>
<Text style={styles.textWaterLeft}>
{dailyGoal - waterDrank}
<Text style={styles.textWaterLeftMeasurement}>ml</Text>
</Text>
<Text style={styles.titleText}>
Left to hit your daily goal!
</Text>
</View>
<View style={styles.wrapper}>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={[
styles.button,
{
backgroundColor: `${
waterDrank >= dailyGoal
? '#4DAC5F'
: '#0064ED'
}`,
},
]}
onPress={() => addWater(-bottle)}
>
<Text style={styles.buttonText}>
-
<FontAwesomeIcon
icon={faTint}
color={'white'}
/>
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.button,
{
backgroundColor: `${
waterDrank >= dailyGoal
? '#4DAC5F'
: '#0064ED'
}`,
},
]}
onPress={() =>
Alert.prompt(
'How much water did you drink?',
'',
[
{
text: 'OK',
onPress: (amount) =>
addWater(amount),
},
]
)
}
>
<Text style={styles.buttonText}>+</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.button,
{
backgroundColor: `${
waterDrank >= dailyGoal
? '#4DAC5F'
: '#0064ED'
}`,
},
]}
onPress={() => addWater(bottle)}
>
<Text style={styles.buttonText}>
+
<FontAwesomeIcon
icon={faTint}
color={'white'}
/>
</Text>
</TouchableOpacity>
</View>
</View>
<StatusBar style="auto" barStyle="dark-content" />
</SafeAreaView>
<View
style={[
styles.indicator,
{
height: `${Math.floor(
(100 / dailyGoal) * waterDrank
)}%`,
backgroundColor: `${
waterDrank >= dailyGoal ? '#51E66E' : '#1782FF'
}`,
},
]}
></View>
</View>
);
}
const styles = StyleSheet.create({
body: {
flex: 1,
backgroundColor: '#152940',
},
container: {
flex: 1,
},
wrapper: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
},
indicator: {
position: 'absolute',
width: '100%',
bottom: 0,
zIndex: -1,
},
textWaterLeft: {
fontSize: 77,
color: '#fff',
fontWeight: 'bold',
},
textWaterLeftMeasurement: {
fontSize: 18,
fontWeight: 'normal',
color: '#fff',
marginTop: 200,
marginBottom: 10,
},
titleText: {
color: '#fff',
fontSize: 18,
marginBottom: 30,
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
flexWrap: 'wrap',
},
button: {
flex: 1,
margin: 10,
backgroundColor: '#0064ED',
borderRadius: 10,
},
buttonText: {
textAlign: 'center',
color: '#fff',
margin: 20,
fontSize: 18,
},
settingsButton: {
height: 40,
width: 40,
alignSelf: 'flex-end',
zIndex: 2,
justifyContent: 'flex-end',
},
settingsMenu: {
position: 'absolute',
height: '100%',
width: '100%',
backgroundColor: '#fff',
zIndex: 200,
},
settingsText: {
marginTop: 30,
},
settingsInput: {
height: 40,
borderColor: 'gray',
borderWidth: 1,
paddingHorizontal: 20,
marginTop: 10,
},
settingsSave: {
marginTop: 30,
textAlign: 'center',
width: '100%',
padding: 15,
borderRadius: 10,
backgroundColor: '#0064ED',
},
});
Ciao, try to use useEffect hook like this:
import React, { useState, useEffect } from 'react';
...
useEffect(() => {
compareDate();
}, [])
In this way compareDate() will be triggered only once at component renders.
I get an array from firebase, it is now sorted alphabetically. If an object contains 'routes' then it will get the text 'Bekijk' button otherwise the text 'coming soon' button, what I would like is that the objects with the name 'Bekijk' are displayed first and then the other objects alphabetically order, does anyone know if that is possible?
This is my code:
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, Image, ImageBackground, StatusBar, ScrollView, Dimensions, TouchableOpacity} from 'react-native';
import { Header, Icon,Button,Rating, AirbnbRating } from 'react-native-elements';
import firebase from 'react-native-firebase';
class routeScreen extends Component {
constructor(props){
super(props);
this.state = {
goverments: [],
}
}
getGovermentData = () => {
let ref = firebase.database().ref('Goverments');
ref.on('value' , snapshot =>{
var state = snapshot.val();
this.setState({
goverments: state,
})
console.log(state);
})
}
componentWillMount(){
this.getGovermentData();
}
render() {
const width = {
width: (Dimensions.get('window').width / 2),
};
return (
<ScrollView>
{
this.state.goverments.sort(function(a, b) {
if(a.name.toLowerCase() < b.name.toLowerCase()) return -1;
if(a.name.toLowerCase() > b.name.toLowerCase()) return 1;
return 0;
}).map((item, i) => (
<View style={[styles.cards, { backgroundColor: (i % 2 == 0) ? '#D1A96E' : '#A58657' }]}>
<View style={styles.leftcolum}>
<Text style={styles.title}>{item.name}</Text>
<Text style={styles.undertitle}>4km - 5km - 7km</Text>
<Image source={require('./assets/images/stars.png')} style={styles.stars}/>
<Button buttonStyle={{
backgroundColor: item.routes ? "#3F494B" : "#018786",
marginTop: 40,
borderRadius: 50,
}} title={item.routes ? "Bekijk" : "Coming soon"}
onPress={() => item.routes ? this.props.navigation.navigate('Location', {govermentData: item}) : '#'}
/>
</View>
<View style={styles.rightcolum}>
<Image source={{uri: item.logoUrl}} style={{width: 150, height: 68}}/>
</View>
</View>
))
}
</ScrollView>
);
}
}
const styles = StyleSheet.create({
cards:{
backgroundColor: '#D1A96E',
borderRadius: 10,
marginTop: 20,
marginRight: 10,
marginLeft: 10,
paddingLeft: 20,
paddingRight: 20,
paddingTop: 20,
paddingBottom: 20,
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'flex-start'
},
stars:{
marginTop: 10,
},
leftcolum:{
width: '50%',
},
rightcolum:{
width: '50%',
paddingTop:30,
paddingLeft:10,
},
title:{
fontSize: 17,
color: '#fff',
marginTop: 5,
fontWeight: '800',
},
undertitle:{
fontSize: 12,
color: '#fff',
fontWeight: '200',
},
button:{
backgroundColor: '#3F494B',
borderRadius: 22,
marginTop: 20,
},
valkenburg:{
backgroundColor: '#A58657',
},
gulpen:{
backgroundColor: '#EBC285',
},
logoValkenburg:{
width: '50%',
paddingTop:10,
paddingLeft:10,
},
logoGulpen:{
width: '50%',
paddingTop:30,
paddingLeft:10,
}
});
export default routeScreen;
Structure of array:
what I would like:
now the array is shown in alphabetical order, that is good, I would only like to show object 1 of Goverments at the top because it contains the value routes, with the others the value routes being empty. so if it is filled, it must show it at the top
const Goverments = [
{
name: 'Valkenburg',
},
{
name: 'Eijsden-Margeaten',
},
{
name: 'Gulpen',
routes: [],
},
];
const SortedGoverments = Goverments.sort(function(a, b) {
if(a.routes) return -1; // new check
if(b.routes) return 1; // new check
if(a.name.toLowerCase() < b.name.toLowerCase()) return -1;
if(a.name.toLowerCase() > b.name.toLowerCase()) return 1;
return 0;
});
console.log("Goverments : ", Goverments);
console.log("SortedGoverments : ", SortedGoverments);
This is my code for Chat Box, the window where I have "In" and "Out" messages are appearing.
import React, { Component } from "react";
import {
StyleSheet,
Text,
View,
TouchableOpacity,
TextInput,
FlatList,
Platform,
AsyncStorage
} from "react-native";
import Tutor from "../image/krutika.jpg";
import {
Container,
Header,
Left,
Input,
Body,
Right,
Thumbnail,
Button
} from "native-base";
import FontAwesome from "react-native-vector-icons/FontAwesome";
import Ionicons from "react-native-vector-icons/Ionicons";
import Icon1 from "react-native-vector-icons/FontAwesome";
import axios from "axios";
export default class ChatBox extends Component {
static navigationOptions = {
header: null
};
state = {
group_msgs: [],
student_id: null
};
renderDate = date => {
return <Text style={styles.time}>{date}</Text>;
};
componentWillMount = () => {
this.loading();
const { navigation } = this.props;
groupName = navigation.getParam("groupName");
group_id = navigation.getParam("group_id");
};
loading = async () => {
const userid = await AsyncStorage.getItem("user_id");
this.state.student_id = userid;
try {
let { data } = await axios.get('https://www.qualpros.com/chat/imApi/getMessage?groupId=6&limit=10&start=0&userId=62').then(response => {
// console.log(response)
if (response.status == 200) {
this.setState({ group_msgs: response.data.response.message });
console.log(response.data.response)
} else {
}
});
} catch (err) {
console.log(err);
}
};
render() {
return (
<Container>
<Header style={{ backgroundColor: "#d91009" }}>
<Left style={{ flex: 1, flexDirection: "row" }}>
<TouchableOpacity
style={styles.backArrow}
onPress={() => this.props.navigation.navigate("ChatScreen")}
>
<FontAwesome name="angle-left" size={30} color="#fff" />
</TouchableOpacity>
<Thumbnail
source={Tutor}
style={{
marginLeft: 8,
width: 30,
height: 30,
borderRadius: 30 / 2
}}
/>
</Left>
<Body>
<Text
onPress={() => {
this.props.navigation.navigate("Groupmembers", {
group_id:group_id,
groupname:groupName,
});
}}
style={{
alignSelf: Platform.OS == "android" ? "center" : null,
fontSize: 17,
color: "#fff"
}}
>
{groupName}
</Text>
</Body>
<Right>
<Button
style={{ backgroundColor: "#d91009" }}
onPress={() => {
this.props.navigation.navigate("TutorCalender");
}}
>
<Icon1 active name="calendar" size={24} color="#FFF" />
</Button>
</Right>
</Header>
<View style={styles.container}>
<FlatList
style={styles.list}
data={this.state.group_msgs}
keyExtractor={item => {
return item.m_id;
}}
renderItem={message => {
console.log(item);
const item = message.item;
let inMessage = (item.sender === this.state.userid) ? 'in' : 'out';
let itemStyle = inMessage ? styles.itemIn : styles.itemOut;
return (
<View style={[styles.item, itemStyle]}>
<View style={[styles.balloon]}>
<Text>{item.message}</Text>
</View>
</View>
);
}}
/>
<View style={styles.footer}>
<View style={styles.inputContainer}>
<TextInput
style={styles.inputs}
placeholder="Write a message..."
underlineColorAndroid="transparent"
onChangeText={name_address => this.setState({ name_address })}
/>
</View>
{/* <TouchableOpacity style={styles.btnSend}>
<Ionicons name="md-send" size={36} color='#d91009' /> style={styles.iconSend} />
</TouchableOpacity> */}
</View>
</View>
</Container>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
list: {
paddingHorizontal: 17
},
footer: {
flexDirection: "row",
height: 60,
backgroundColor: "#eeeeee",
paddingHorizontal: 10,
padding: 5
},
btnSend: {
//color: "#d91009",
width: 40,
height: 40,
borderRadius: 360,
alignItems: "center",
justifyContent: "center"
},
iconSend: {
width: 30,
height: 30,
alignSelf: "center"
},
inputContainer: {
borderBottomColor: "#F5FCFF",
backgroundColor: "#FFFFFF",
borderRadius: 30,
borderBottomWidth: 1,
height: 40,
flexDirection: "row",
alignItems: "center",
flex: 1,
marginRight: 10
},
inputs: {
height: 40,
marginLeft: 16,
borderBottomColor: "#FFFFFF",
flex: 1
},
balloon: {
maxWidth: 250,
padding: 15,
borderRadius: 20
},
itemIn: {
alignSelf: "flex-start",
backgroundColor: "#eeeeee"
},
itemOut: {
alignSelf: "flex-end",
backgroundColor: "#DCF8C5"
},
time: {
alignSelf: "flex-end",
margin: 15,
fontSize: 12,
color: "#808080"
},
item: {
marginVertical: 14,
flex: 1,
flexDirection: "row",
borderRadius: 300,
padding: 1
}
});
I am using axios to fetch the api, the api response is coming as an Array inside the array but nothing is coming on the screen.
I can get it with storing response upto message but then I can't have the loop on messages.
Please help.
Thanks in advance
When doing a GET request to the endpoint in your code the response looks as follows:
{
"status":{
"code":200,
"message":"Success"
},
"totalMessage":6,
"recentMessageId":228,
"response":[
...
]
}
Inside the response object there's an array of message objects so you can't use response.data.response.message when setting state. That part of your code needs to be:
this.setState({ group_msgs: response.data.response });
Now you should be able to iterate through the group_msgs object to get the message key value for each item in the array.
Also in the FlatList component you should have
keyExtractor={item => {
return item.message.m_id;
}}
Your renderItem seems to be wrong as well, see should be something like this:
renderItem={ ({item}) => {
let inMessage = (item.sender.usedId === this.state.userid) ? 'in' : 'out';
let itemStyle = inMessage ? styles.itemIn : styles.itemOut;
return (
<View style={[styles.item, itemStyle]}>
<View style={[styles.balloon]}>
<Text>{item.message.message}</Text>
</View>
</View>
);
}}
I strongly suggest you take a look at the structure of the response object since that's where you are failing at the moment.