How do i style mapped data in a function in react native - javascript

How is styling done after mapping data into a function in react native. The data is displayed correctly but in a raw format. I'd like the data being mapped to be styled into rows with space between each item. I have tried using a flatlist and it throws an error of invariant violation: tried to get frame for out of the range index nan. Kindly help.
import React, {useEffect, useState} from 'react'
import { Text, View, ActivityIndicator, ScrollView, StyleSheet } from 'react-native'
import axios from '../../utils/axios'
//import CurrencyPair from '../../CurrencyPair'
function HomeScreen() {
const [data, setData] = useState([])
const [isLoading, setIsloading] = useState(true)
useEffect(() => {
const interval = setInterval(() => {
const fetchpairs = async() => {
const results = await axios.get('/v3/accounts/{AccountId}/pricing?instruments=AUD_CAD%2CAUD_CHF%2CAUD_JPY%2CAUD_NZD%2CAUD_USD%2CCAD_CHF%2CCAD_JPY%2CCHF_JPY%2CEUR_AUD%2CEUR_CAD%2CEUR_CHF%2CEUR_GBP%2CEUR_NOK%2CEUR_NZD%2CEUR_USD%2CGBP_AUD%2CGBP_CAD%2CGBP_CHF%2CGBP_USD%2CGBP_JPY%2CNZD_CAD%2CNZD_CHF%2CNZD_JPY%2CUSD_CAD%2CUSD_JPY%2CUSD_CHF%2CUSD_ZAR%2CUSD_MXN')
console.log(results.data)
setData(results.data)
setIsloading(false)
}
fetchpairs()
},1000)
}, []);
if(isLoading) {
return (
<ActivityIndicator size="large"/>
)
}
else
return (
<ScrollView
contentContainerStyle={styles.contentContainer}
>
{data.prices && data.prices.map((prices, index) => {
return (
<Text key={index} style={styles.maintext}>
{data.prices[index].instrument}
{data.prices[index].closeoutAsk}
{data.prices[index].closeoutBid}
</Text>
)
})
}
</ScrollView>
)
}
const styles = StyleSheet.create({
contentContainer:{
flex: 1,
marginTop: 20,
justifyContent: "space-around"
}
})
export default HomeScreen

Just use flex to style.
{data.prices && data.prices.map((prices, index) => {
return (
<View
key={index}
style={{
flexDirection: 'row'
//justifyContent:'space-between'
}}>
<Text style={styles.maintext}>{data.prices[index].instrument}</Text>
<Text style={(styles.maintext, { marginLeft: 4 })}>{data.prices[index].closeoutAsk}</Text>
<Text style={(styles.maintext, { marginLeft: 4 })}>{data.prices[index].closeoutBid}</Text>
</View>
)
})
}

Related

Async Storage not working (React native expo), no error given in console, but everytime I reload nothing is stored

I'm trying to use Async Storage for a note app, I created a component called task.js as a template for todos, an navigation.js component for nav, and home.js for the main screen all display with <navigation /> inapp.js, I added a funcction to store object value using async storage, but is not working, everytime I hard reload the app everything will be gone but it is not giving me any errors, I don't know where to start
here is my Home.js
import React, {useState} from 'react';
import { Keyboard, KeyboardAvoidingView, Platform, StyleSheet, Text,
TextInput, TouchableOpacity, View, SafeAreaView, ScrollView, Image } from 'react-native';
import Task from '../components/Task';
import AsyncStorage from '#react-native-async-storage/async-storage';
export default function Home({ navigation }) {
const [task, setTask] = useState();
const [taskItems, setTaskItems] = useState([]);
React.useEffect ( () => {
save(taskItems);
}, [taskItems])
React.useEffect (() => {
getsave();
}, [])
const handleAddTask = () => {
Keyboard.dismiss();
setTaskItems([...taskItems, task])
setTask(null);
}
const completeTask = (index) => {
let itemsCopy = [...taskItems];
itemsCopy.splice (index, 1);
setTaskItems(itemsCopy)
}
const save = async taskItems =>{
try {
const savetask = JSON.stringify(taskItems)
await AsyncStorage.setItem('tasksave', savetask)
} catch (e) {
console.log(e);
}
};
const getsave = async () => {
try {
const taskItems = await AsyncStorage.getItem('tasksave');
if (taskItems != null){
setTaskItems(JSON.parse(taskItems));
}
} catch (error) {
console.log(e);
}
};
return (
<SafeAreaView style={styles.container}>
<View style={styles.tasksWrapper}>
<Text style={styles.sectionTitle}>Your stuff:</Text>
<TouchableOpacity onPress={() => navigation.navigate('About')}>
<Text style={styles.about}>About</Text>
</TouchableOpacity>
<ScrollView style={styles.items}>{
taskItems.map((item, index) => {
return (
<View key={index}>
<TouchableOpacity onPress={ () => navigation.navigate("Gas", {item})}>
<Task text={item} navigation={navigation} />
</TouchableOpacity>
<TouchableOpacity onPress={() => completeTask(index)} style={styles.deleteW}>
<Image style={styles.delete} source={require('../components/remove.png')}></Image>
</TouchableOpacity>
</View>
)
})
}
</ScrollView>
</View>
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={styles.textwrapper}>
<TextInput style={styles.input} placeholder={'message'} value={task} onChangeText={text => setTask(text)}></TextInput>
<TouchableOpacity onPress={() => handleAddTask()}>
<View style={styles.addWrap}>
<Text style={styles.add}>+</Text>
</View>
</TouchableOpacity>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
Here's my Task.js:
import React from "react";
import { View, Text, StyleSheet, Image, TouchableOpacity } from "react-native";
const Task = (props, {navigation}) => {
return (
<View style={styles.item}>
<View style={styles.itemleft}>
<Image style={styles.lightball} source={require('./arabic.png')}></Image>
<Text style={styles.itemtext}>{props.text}</Text>
</View>
<Image style={styles.arrow} source={require('./rightarrow.png')}></Image>
</View>
)
}
const styles = StyleSheet.create({
export default Task;
I hope is a quick read, I took out all the style stuff but this is still kinda long sorry, if you think it has something to do with my app.js or nav.js I can give you those too, I usually slove these bugs on my own but I just have no idea where to begin cause I'm not getting any error messages, thank you

Trying to come out with a filter function for my app. Render Error: Too many re-renders. React limits the number of renders

The idea I have for this to work is to copy my main array from firebase (Array with all my info) into a temporary array. Then I will filter this temporary array and have it displayed in flatlist. The onPress for the buttons serves to select the type of information to be filtered (Eg type 1 or 2 or 3).
import React, { useState, setState, useEffect } from 'react';
import { View, Text, StyleSheet, ImageBackground, FlatList, Button, TouchableHighlight } from 'react-native'
import Card from '../components/Card';
import colors from '../config/colors';
import {MaterialCommunityIcons} from '#expo/vector-icons'
import { useNavigation } from '#react-navigation/core';
import AppButton from '../components/AppButton'
import { SearchBar } from 'react-native-screens';
import { Firestore, getDoc, collection, getDocs,
addDoc, deleteDoc, doc,
query, where, onSnapshot
} from 'firebase/firestore';
import {db} from '../../firebase';
import { async } from '#firebase/util';
//run: 1
//swim: 2
//cycle: 3
function EventsPage(props) {
const [events, setEvents] = useState([]);
const [bool, setBool] = useState(false);
const [arr, setArr] = useState([])
const colRef = collection(db, 'events');
const q = query(colRef, where('type', '>=', 0))
onSnapshot(q, (snapshot) => {
const events = []
snapshot.docs.forEach((doc) => {
events.push({...doc.data()}) //put the data into an array
})
if (bool === false) {
setEvents(events);
setBool(true)
}
})
const updateSearch = search => {
setArr({ search }, () => {
if (type == search) {
setArr({
data: [...arr.temp]
});
return;
}
arr.data = arr.temp.filter(function(item){
return item.name.includes(search);
}).map(function({date, subTitle, title, type}){
return {date, subTitle, title, type};
});
});
};
return (
<View style = {styles.container}>
<ImageBackground
source = {require('../assets/splash-page.jpg')}
style = {{width: '100%', height: '100%'}}
blurRadius={8}
>
<View style = {styles.backIcon}>
<MaterialCommunityIcons name='arrow-left-bold' color="black" size={35} onPress={() => {
navigation.replace("Connect_me")
}} />
</View>
<Text style = {styles.text}>EVENTS</Text>
<View style = {styles.buttons}>
<Button title={'All'} />
<Button title={'Run'} onPress = {updateSearch(1)}/>
<Button title={'Swim'} onPress = {updateSearch(2)}/>
<Button title={'Cycle'} onPress = {updateSearch(3)}/>
</View>
<FlatList
data={arr.data}
renderItem={({ item }) => (
<View style = {styles.cardContainer}>
<Card title={item.title} subTitle = {item.subTitle}/>
</View>
)}
/>
<Text></Text>
<Text></Text>
<Text></Text>
<Text></Text>
<Text></Text>
</ImageBackground>
</View>
// trolling
);
}
const styles = StyleSheet.create({
text: {
fontSize: 80,
textAlign:'center',
paddingBottom: 20,
color: colors.primary,
fontWeight: 'bold',
},
container: {
backgroundColor: 'white',
},
cardContainer: {
width: '95%',
alignSelf: 'center'
},
backIcon: {
paddingLeft: 10,
paddingTop: 30,
},
searchIcon: {
paddingLeft: 10,
paddingTop: 15,
position: 'relative',
left: 330,
bottom: 47
},
buttons: {
flexDirection: 'row',
padding: 20,
}
})
export default EventsPage;
Side effects code like listening to data change events should be handled inside the useEffect hook.
The app continues to listen to data change events for each component re-render which causes an infinity loop.
useEffect(() => {
const unsubscribe = onSnapshot(q, (snapshot) => {
const events = [];
snapshot.docs.forEach((doc) => {
events.push({ ...doc.data() }); //put the data into an array
});
if (bool === false) {
setEvents(events);
setBool(true);
}
});
// unsubscribe to data change events when component unmount
return () => {
unsubscribe();
};
}, []);

using Onclick, fetch api data in react native

I am new to React Native.
I am facing an issue with this view. Basically it is something like this when you click a button it generates any random number, now this random number becomes an id and it goes to at the end of the API url, And using this new API - with ID at the end of it. - data gets fetched. Now i've divided this task in two parts generating random number code (i.e. snippet 1) and fetching data from api ( i.e. snippet 2). As of now, I don't know how to combine them because i am new to react native so a little help here would be appreciated from anyone.
Snipppet 1
import { StyleSheet, View, Button, Text } from 'react-native';
export default class MyProject extends Component {
constructor(){
super();
this.state={
// This is our Default number value
NumberHolder : 0
}
}
GenerateRandomNumber=()=>
{
var RandomNumber = Math.floor(Math.random() * 5000) + 1 ;
this.setState({
NumberHolder : RandomNumber
})
}
render() {
return (
<View style={styles.MainContainer} >
<Text style={{marginBottom: 10, fontSize: 20}}>{this.state.NumberHolder}</Text>
<Button title="Generate Random Number" onPress={this.GenerateRandomNumber} />
</View>
);
}
}
const styles = StyleSheet.create(
{
MainContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}
});
Snippet 2
import React, { useState } from "react";
import { Box, FlatList, Center, NativeBaseProvider, Button } from "native-base";
import { StyleSheet, View, ActivityIndicator, Text, TouchableOpacity, Image } from 'react-native';
export default function MyFUnction() {
const [data, setData] = useState(null);
const [visible, setVisible] = useState(true);
const fetchData = async () => {
const resp = await fetch("https://jsonplaceholder.typicode.com/photos/7");
const data = await resp.json();
setData(data);
setVisible(false);
};
const renderItem = ({ item }) => {
return (
<TouchableOpacity style={styles.list}>
<Text>{item.title}</Text>
</TouchableOpacity>
);
};
return (
<NativeBaseProvider>
<Center flex={1}>
{visible && <Button onPress={() => fetchData()}>Press</Button>}
{data && (
<FlatList
data={data}
renderItem={(item) => this.renderItem(item)}
keyExtractor={(item) => item.id.toString()}
/>
)}
</Center>
</NativeBaseProvider>
);
}
const styles = StyleSheet.create({
list: {
paddingVertical: 4,
margin: 5,
backgroundColor: '#fff',
},
});
Thanks in advance!!
I think you must understand components clearly! React is component based! But your case is not 2 components! You have a component for fetching api and showing in list! Generating a random number is not a component, but it is a method(or function) in your list component! I think it is better to use one component for list and wrap a function to it for generating random number.
import React, { useState } from "react";
import { Box, FlatList, Center, NativeBaseProvider, Button } from "native-base";
import { StyleSheet, View, ActivityIndicator, Text, TouchableOpacity, Image } from 'react-native';
export default function MyFUnction() {
const [data, setData] = useState(null);
const [visible, setVisible] = useState(true);
const generatRandomNumber = () => {
return Math.floor(Math.random() * 5000) + 1
}
const fetchData = async () => {
const resp = await fetch(`https://jsonplaceholder.typicode.com/photos/${generatRandomNumber()}`);
const data = await resp.json();
setData(data);
setVisible(false);
};
const renderItem = ({ item }) => {
return (
<TouchableOpacity style={styles.list}>
<Text>{item.title}</Text>
</TouchableOpacity>
);
};
return (
<NativeBaseProvider>
<Center flex={1}>
{visible && <Button onPress={() => fetchData()}>Press</Button>}
{data && (
<FlatList
data={data}
renderItem={(item) => this.renderItem(item)}
keyExtractor={(item) => item.id.toString()}
/>
)}
</Center>
</NativeBaseProvider>
);
}
const styles = StyleSheet.create({
list: {
paddingVertical: 4,
margin: 5,
backgroundColor: '#fff',
},
});
But if you want to passing data between components you are have, it is not related to function or class component and you can pass data between them with props! So your code like this:
Random Number Component
import { StyleSheet, View, Button, Text } from 'react-native';
export default class MyProject extends Component {
constructor(props){ //edited
super(props); //edited
this.state={
// This is our Default number value
NumberHolder : 0
}
}
GenerateRandomNumber=()=>
{
var RandomNumber = Math.floor(Math.random() * 5000) + 1 ;
this.props.randomNumber(RandomNumber)
}
render() {
return (
<View style={styles.MainContainer} >
<Text style={{marginBottom: 10, fontSize: 20}}>{this.state.NumberHolder}</Text>
<Button title="Generate Random Number" onPress={this.GenerateRandomNumber} />
</View>
);
}
}
const styles = StyleSheet.create(
{
MainContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}
});
Your list component:
import React, { useState } from "react";
import { Box, FlatList, Center, NativeBaseProvider, Button } from "native-base";
import { StyleSheet, View, ActivityIndicator, Text, TouchableOpacity, Image } from 'react-native';
// import MyProject
export default function MyFUnction() {
const [data, setData] = useState(null);
const [visible, setVisible] = useState(true);
const [number, setNumber] = useState(null);
const fetchData = async () => {
const resp = await fetch(`https://jsonplaceholder.typicode.com/photos/${number}`);
const data = await resp.json();
setData(data);
setVisible(false);
};
const renderItem = ({ item }) => {
return (
<TouchableOpacity style={styles.list}>
<Text>{item.title}</Text>
</TouchableOpacity>
);
};
return (
<NativeBaseProvider>
<Center flex={1}>
<MyProject radomNumber={(number) => setNumber(number)}
{visible && <Button onPress={() => fetchData()}>Press</Button>}
{data && (
<FlatList
data={data}
renderItem={(item) => this.renderItem(item)}
keyExtractor={(item) => item.id.toString()}
/>
)}
</Center>
</NativeBaseProvider>
);
}
const styles = StyleSheet.create({
list: {
paddingVertical: 4,
margin: 5,
backgroundColor: '#fff',
},
});
thanks everyone for helping me.
here i am posting answer to my question, if anybody in future need an answer.
import React, { useEffect, useState, Component } from 'react';
import { StyleSheet, View, Button, FlatList, Text, Image } from 'react-native';
export default class MyProject extends Component {
constructor(){
super();
this.state={
// This is our Default number value
NumberHolder : 1,
books: []
}
}
GenerateRandomNumber=()=>
{
var RandomNumber = Math.floor(Math.random() * 5000) + 1;
fetch(`https://jsonplaceholder.typicode.com/photos/${RandomNumber}`)
.then((response) => response.json())
.then(booksList => {
this.setState({ books: booksList });
});
this.setState({
NumberHolder : RandomNumber
})
}
render() {
let Image_Http_URL ={ uri: 'https://reactnativecode.com/wp-content/uploads/2017/05/react_thumb_install.png'};
return (
<View style={styles.MainContainer} >
<Text style={{marginBottom: 10, fontSize: 20}}>{this.state.NumberHolder}</Text>
<Image
style={{width: '100%', height: 200,resizeMode : 'stretch' }}
source={{uri: this.state.books.url}}
/>
<Text style={{marginBottom: 10, fontSize: 12}}>{this.state.books.title}</Text>
<Text style={{marginBottom: 10, fontSize: 12}}>{this.state.books.url}</Text>
<Text style={{marginBottom: 10, fontSize: 12}}>{this.state.books.thumbnailUrl}</Text>
<Button title="Generate Random Number" onPress={this.GenerateRandomNumber} />
</View>
);
}
}
const styles = StyleSheet.create(
{
MainContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}
});

Conditional rendering with React Hooks : loading

I am learning how to use React Hooks and have been stuck for many hours on something that's supposed to be very simple.
I am trying to display a a text if the state variable "loading" is true. If it's false, I want to display something else.
No matter what I try, "loading" is always false or at least, the UI does not appear to reflect its value.
here is the code:
import React, {useState, useEffect} from 'react';
import {View, SafeAreaView, Text} from 'react-native';
const testScreen= (props) => {
const [loading, setLoading ] = useState(true);
useEffect(() => {
setLoading(false);
}, []);
if(loading)
{
return <Text>Hi</Text>;
}
else
{
return<Text.Hey</Text>
}
}
export default testScreen;
Any help will be more than welcome and I am sorry if this is very basic.
UPDATE: Here is the actual code I am working with. SetLoading is supposed to update the state variable to false but never does or at least, the UI des not render.
import React, {useState, useEffect} from 'react';
import {View, SafeAreaView, Text, ActivityIndicator} from 'react-native';
import CategoryTag from '../Components/CategoryTag';
import firestore from '#react-native-firebase/firestore';
const CategoryScreen = (props) => {
const topicCollection = firestore().collection('Topics')
.where("active","==",true);
//hooks for topics
const [topics,setTopics] = useState([]);
const [loading, setLoading ] = useState(true);
//get all active topics
useEffect(() => {
return topicCollection.onSnapshot(querySnapshot => {
const list = [];
querySnapshot.forEach(doc => {
const { active, name } = doc.data();
list.push({
id: doc.id,
active,
name,
});
});
setTopics(list);
setLoading(false);
});
}, []);
const renderTopics = () =>{
return(
topics.map((item) =>{
return(
<CategoryTag key = {item.id}
color={userTopics.includes(item.name) ?"#51c0cc":"#303239"}
name = {item.name}
isSelected = {userTopics.includes(item.name)}
handleClick = {addTopicToUserTopicCollection}
/>
)
})
)
}
if(loading)
{
return (
<SafeAreaView style={{flex:1, backgroundColor:"#455a65"}}>
<View style={{width:200, padding:20, paddingTop:60}}>
<Text style ={{fontSize:25, fontWeight:"bold",
color:"#fff"}}>What are you</Text>
<Text style ={{fontSize:22, color:"#fff"}}>interested in?
</Text>
</View>
<View style={{flex:1, alignItems:"center",
justifyContent:"center", alignSelf:"center"}}>
<ActivityIndicator />
</View>
</SafeAreaView>
)
}
else // this never runs
{
return (
<SafeAreaView style={{flex:1, backgroundColor:"#455a65"}}>
<View>
<View style={{width:200, padding:20, paddingTop:60}}>
<Text style ={{fontSize:25, fontWeight:"bold",
color:"#fff"}}>What are you</Text>
<Text style ={{fontSize:22, color:"#fff"}}>interested in?
</Text>
</View>
<View style ={{flexDirection:"column", paddingTop:20}}>
<View style ={{padding:15, paddingTop:15,
marginBottom:15,
flexWrap:"wrap", flexDirection:"row"}}>
{renderTopics(topics)}
</View>
</View>
</View>
</SafeAreaView>
);
}
}
export default CategoryScreen;
You are immediately setting your setLoading state to false and therefore loading text might be rendering for fraction of second, or not at all, like a glitch. Try setting setLoading with a timeout and then you will see the intended behaviour.
const TestScreen= (props) => {
const [loading, setLoading ] = useState(true);
useEffect(() => {
setTimeout(()=>setLoading(false), 3000);
}, []);
if(loading)
{
return <Text>Hi</Text>;
}
else
{
return<Text>hey</Text>
}
}

Search bar glitching out in React Native

I'm making a search bar that displays results live. I've managed to do it properly utilizing SearchBar from 'react-native-elements'. Firstly I had it written as a class component, but decided to rewrite it as a functional component. After rewriting it I'm encountering a bug where the keyboard closes after one letter as seen in the video here
Here is the code of the component
import React, { Component, useEffect, useState } from "react";
import { View, Text, FlatList, TextInput, ListItem } from "react-native";
import { SearchBar } from "react-native-elements";
import { Button } from 'react-native-paper'
import Header from "../navigation/Header";
export default function AktSelect() {
const [data, setData] = useState([])
const [value, setValue] = useState('')
const [akt, setAkt] = useState([])
useEffect(() => {
fetch("http://192.168.5.12:5000/aktprikaz", {
method: "get"
})
.then(res => res.json())
.then(res => setAkt(res));
}, []);
function renderSeparator() {
return (
<View
style={{
height: 1,
width: "100%",
backgroundColor: "#CED0CE"
}}
/>
);
}
function searchItems(text) {
const newData = akt.filter(item => {
const itemData = `${item.title.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
setData(newData)
setValue(text)
}
function renderHeader() {
return (
<SearchBar
placeholder=" Type Here...Key word"
onChangeText={text => searchItems(text)}
value={value}
lightTheme={true}
/>
);
}
return (
<View
style={{
flex: 1,
width: "98%",
alignSelf: "center",
justifyContent: "center"
}}
>
<Header title='Pretraživanje aktivnosti' />
<FlatList
data={data}
renderItem={({ item }) => (
<View style={{flex: 1}}>
<Text style={{ padding: 10 }}>{item.title} </Text>
<View style={{flexDirection:'row'}}>
<Text style={{ padding: 10 }}>{item.start_time} </Text>
<Button style={{justifyContent: 'flex-end', alignContent: 'flex-end', width:'30%'}} mode='contained' onPress={() => console.log('hi')}>hi</Button>
</View>
</View>
)}
keyExtractor={item => item.id.toString()}
ItemSeparatorComponent={renderSeparator}
ListHeaderComponent={renderHeader}
/>
</View>
);
}
The old class component can be found here

Categories