The data being fetched from the api is needed for other purposes in the modal. How do i pass data: {currency.data.prices[index].instrument} {currency.data.prices[index].closeoutAsk} {currency.data.prices[index].closeoutBid} that is in a component to a modal that is in the same component. Below is the code:
//HomeScreen
import React, {useContext, useState} from 'react'
import { Text, View, ScrollView, TouchableOpacity, Modal, TextInput } from 'react-native'
import {ListItem, Card, Button, Icon} from 'react-native-elements'
//import CurrencyPair from '../../CurrencyPair'
import {firebase} from '../../../firebase/config'
import {CurrencyContext} from '../../../context/Context'
import styles from '../LoginScreen/styles'
function HomeScreen() {
const currency = useContext(CurrencyContext);
const [modalopen, setModalOpen] = useState(false)
return (
<ScrollView>
<Modal
visible={modalopen}
animationType={"fade"}
>
<View style={styles.modal}>
<View>
<Text style={{textAlign: "center", fontWeight: "bold"}}>
CreateAlert
</Text>
<TouchableOpacity style={styles.button} onPress={() => setModalOpen(false)}>
<Text style={styles.buttonTitle}>OK</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
<Card>
<Text style={{textAlign: "center"}}>
Welcome
</Text>
<Button title="Sign Out" type="outline" onPress ={() => firebase.auth().signOut()}/>
<Button title="My Alerts" onPress ={() =>navigation.navigate("AlertScreen") }/>
</Card>
<View>
{currency.data.prices && currency.data.prices.map((prices, index) => {
return (
<ListItem
key={index}
onPress = {() => setModalOpen(true)}
bottomDivider>
<ListItem.Content>
<ListItem.Title>
{currency.data.prices[index].instrument} {currency.data.prices[index].closeoutAsk} {currency.data.prices[index].closeoutBid}
</ListItem.Title>
</ListItem.Content>
</ListItem>
)
})
}
</View>
</ScrollView>
)
}
export default HomeScreen
//Context
import React, {createContext, useState, useEffect}from 'react'
import {ActivityIndicator} from 'react-native'
import axios from '../utils/axios'
const CurrencyContext = createContext();
const CurrencyProvider =(props) => {
const [data, setData] = useState([])
const [isLoading, setIsloading] = useState(true)
useEffect(() => {
const interval = setInterval(() => {
const fetchpairs = async() => {
const results = await axios.get('/v3/accounts/101-004-14328428-002/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')
setData(results.data)
setIsloading(false)
}
fetchpairs()
},1000)
}, []);
if(isLoading) {
return (
<ActivityIndicator size="large"/>
)
}else
return (
<CurrencyContext.Provider
value={{
data,
setData,
isLoading,
setIsloading
}}>
{props.children}
</CurrencyContext.Provider>
)
}
export {CurrencyProvider, CurrencyContext}
you can create another state variable to store the clicked index.
const [clickedIndex, setClickedIndex] = useState(0);
then use that in the onPress event.
onPress = {() => {setModalOpen(true);setClickedIndex(index);}
then you can use this same index to display what you want in the modal.
<Modal
visible={modalopen}
animationType={"fade"}
>
<View style={styles.modal}>
<View>
<Text style={{textAlign: "center", fontWeight: "bold"}}>
{currency.data.prices[clickedIndex].instrument}
</Text>
<TouchableOpacity style={styles.button} onPress={() => setModalOpen(false)}>
<Text style={styles.buttonTitle}>OK</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
Related
I am using redux and I have an issue with dispatch request to firestore. When I query the data, I get the correct data and after one second it disappears.
this is the Home screen where I want to show the data queried from firestore.
in my data structure each product has a categories array which has the categories for this product. I want to show these data in three different places in my home screen. hopefully, I could clearly describe my issue
import { useSelector, useDispatch } from 'react-redux';
import { useNavigation } from '#react-navigation/native';
import * as productActions from '../store/actions/products';
import * as categoriesActions from '../store/actions/Categories';
import * as promotionActions from '../store/actions/promotions';
const Home = ()=>{
const dispatch = useDispatch();
const navigation = useNavigation();
useEffect(()=>{
dispatch(productActions.fetchproducts());
dispatch(categoriesActions.fetchCategories());
dispatch(promotionActions.fetchPromotionProducts());
},[])
const categoryObject = useSelector(state=>state.categories.availableCategory)
const promotionArr = useSelector(state=>state.promoionProducts.promotionProducts)
const categoryTitle = [];
const categoryId = []
for(const key in categoryObject){
categoryTitle.push(categoryObject[key].title)
categoryId.push(categoryObject[key].id)}
return(
<ScrollView>
<ImageCarasoul pro={promotionArr}/>
<View style={styles.catName}>
<Text style={styles.catText}>{categoryTitle[0]}</Text>
<TouchableOpacity onPress={()=>{navigation.navigate("ProductsList", {catId: categoryId[0] })}}>
<Text style={styles.showAllText}>عرض الكل</Text>
</TouchableOpacity>
</View>
<Card catId={categoryId[3]}/>
<CategoriesList />
<View style={styles.catName}>
<Text style={styles.catText}>{categoryTitle[1]}</Text>
<TouchableOpacity onPress={()=>{navigation.navigate("ProductsList", {catId: categoryId[1] })}}>
<Text style={styles.showAllText}>عرض الكل</Text>
</TouchableOpacity>
</View>
<Card catId={categoryId[1]}/>
<View style={styles.catName}>
<Text style={styles.catText}>{categoryTitle[2]}</Text>
<TouchableOpacity onPress={()=>{navigation.navigate("ProductsList", {catId:categoryId[2]})}}>
<Text style={styles.showAllText}>عرض الكل</Text>
</TouchableOpacity>
</View>
<Card catId={categoryId[2]}/>
<Brands />
</ScrollView>
)};
and this is the card compenent
import { useSelector,useDispatch } from "react-redux";
import * as cartActions from '../store/actions/cart';
import * as categoryProductsAction from '../store/actions/categoryProducts';
const Card = (catId)=>{
//receive categoryID and fetc
const catProducts = ()=>{
dispatch(categoryProductsAction.fetchCategoryProducts(catId))
}
useEffect(()=>{
catProducts();
},[catId]);
const categoryProductsArr = useSelector(state=>state.categoryProducts.availableCategoryProducts)
const dispatch = useDispatch()
const navigation = useNavigation()
return(
<View >
<FlatList
horizontal
showsHorizontalScrollIndicator={false}
data={categoryProductsArr}
renderItem={({item})=>{
return(
<View>
<View style={styles.cardView}>
<TouchableOpacity onPress={()=>{navigation.navigate("ProductDetails", {itemId: item.id, catId: item.categoryId, productTitle: item.title})}} style={styles.imageView}>
<Image style={styles.image} source={{uri: item.image}}/>
</TouchableOpacity>
<TouchableOpacity onPress={()=>{navigation.navigate("ProductDetails", {itemId: item.id, catId: item.categoryId, productTitle: item.title})}} style={styles.priceView}>
<View>
<Text style={styles.price}> ج.م {item.price}</Text>
</View>
<View style={styles.priceView}>
<Text style={styles.description}>{item.description}</Text>
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={()=>{dispatch(cartActions.addToCart(item, 1)) }}
style={styles.addToCartView}>
<Text style={styles.renderAddToCart}>اضف للسلة</Text>
</TouchableOpacity>
</View>
</View>
)
}}
/>
</View>
)};
this is th action
export const SET_CATEGORYPRODUCTS = "SET_CATEGORYPRODUCTS";
import {collection, getDocs, query, where } from "firebase/firestore";
import { db } from '../../config';
export const fetchCategoryProducts = ({catId})=>{
return async dispatch=>{
const categoryProductsCollection = query(collection(db, "Product"), where("categories", "array-contains", catId))
const getCategoryProducts = getDocs(categoryProductsCollection);
const categoryProducts = (await getCategoryProducts).docs.map(item=>{
const data = item.data();
data.id = item.id;
return data
})
console.log(categoryProducts)
dispatch({type: SET_CATEGORYPRODUCTS, categoryProduct: categoryProducts})
}}
and thsis is the reducer
import { SET_CATEGORYPRODUCTS } from "../actions/categoryProducts";
const initialState = {
availableCategoryProducts: []
};
export default (state = initialState, action)=>{
switch (action.type){
case SET_CATEGORYPRODUCTS:
return{
availableCategoryProducts: action.categoryProduct
}
}
return state};
Maybe I am getting this error because the props are passed is a string and toFixed() cannot work on it but I am trying to pass number and for that purpose, I have also added + in after price like this +pass to convert into a number but still I am getting this error.
ProductItem.js:
const ProductItem = (props) => {
return (
<View style={styles.product}>
<View style={styles.Touchable}>
<TouchableNativeFeedback onPress={props.onSelect} useForeground>
<View>
<View style={styles.imageContainer}>
<Image style={styles.image} source={{ uri: props.image }} />
</View>
<View style={styles.details}>
<Text style={styles.title}>{props.title}</Text>
<Text style={styles.price}>
{props.price.toFixed(2)} //Here I am getting this error
</Text>
</View>
<View style={styles.actions}>{props.children}</View>
</View>
</TouchableNativeFeedback>
</View>
</View>
);
};
In the above file, I am getting this error.
EditUserProduct.js :
import React, { useState, useCallback, useEffect } from "react";
import {
View,
ScrollView,
Text,
TextInput,
Platform,
StyleSheet,
} from "react-native";
import { useSelector, useDispatch } from "react-redux";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import CustomHeaderButton from "../../components/UI/HeaderButton";
import * as productActions from "../../store/actions/products";
const EditProductScreen = (props) => {
const dispatch = useDispatch();
const prodId = props.navigation.getParam("productId");
const editedProduct = useSelector((state) =>
state.products.userProducts.find((prod) => prod.id === prodId)
);
console.log(editedProduct);
const [title, setTitle] = useState(editedProduct ? editedProduct.title : "");
const [imageUrl, setImageUrl] = useState(
editedProduct ? editedProduct.imageUrl : ""
);
const [price, setPrice] = useState("");
const [description, setDescription] = useState(
editedProduct ? editedProduct.description : ""
);
const submitHandler = useCallback(() => {
if (editedProduct) {
dispatch(
productActions.updateProduct(prodId, title, description, imageUrl)
);
} else {
dispatch(
productActions.createProduct(
prodId,
title,
description,
imageUrl,
+price
)
);
}
}, [dispatch, prodId, title, description, imageUrl, price]);
useEffect(() => {
props.navigation.setParams({ submit: submitHandler });
}, [submitHandler]);
return (
<ScrollView>
<View style={styles.form}>
<View style={styles.formControl}>
<Text style={styles.label}>Title</Text>
<TextInput
style={styles.input}
value={title}
onChangeText={(text) => setTitle(text)}
/>
</View>
<View style={styles.formControl}>
<Text style={styles.label}>Image URL</Text>
<TextInput
style={styles.input}
value={imageUrl}
onChangeText={(text) => setImageUrl(text)}
/>
</View>
{editedProduct ? null : (
<View style={styles.formControl}>
<Text style={styles.label}>PRICE</Text>
<TextInput
style={styles.input}
value={price}
onChangeText={(text) => setPrice(text)}
/>
</View>
)}
<View style={styles.formControl}>
<Text style={styles.label}>Description</Text>
<TextInput
style={styles.input}
value={description}
onChangeText={(text) => setDescription(text)}
/>
</View>
</View>
</ScrollView>
);
};
EditProductScreen.navigationOptions = (navigationData) => {
const submitFN = navigationData.navigation.getParam("submit");
return {
headerTitle: navigationData.navigation.getParam("productId")
? "Edit Product"
: "Add Product",
headerRight: () => (
<HeaderButtons HeaderButtonComponent={CustomHeaderButton}>
<Item
title="Save"
iconName={
Platform.OS === "android" ? "md-checkmark" : "ios-checkmark"
}
onPress={submitFN}
/>
</HeaderButtons>
),
};
};
In the above file I have added +price to convert it into a number but still getting this error.
I have also tried parseFloat(props.price.toFixed(2)) then I am getting NaN.
How can I solve this error?
First confirm that props.price is defined:
console.log("price:",props.price)
if it is defined, see the type :
console.log("typeof price", typeof props.price)
I assume its type is string:
<Text style={styles.price}>
{Number(props.price).toFixed(2)}
</Text>
parseFloat(props.price.toFixed(2)) this gives you Nanindicates that props.price.toFixed(2) cannot be converted to number, most likely it is undefined that is why you get Nan
I'm buiding an application that receives foreign exchange currency pairs e.g EURUSD with their respective prices e.g EURUSD AskPrice: 0.90345 BidPrice: 0.90365 . The user of the application is supposed to set the price in a textInput at which they would like to be alerted once that price is reached. I have tried creating a function for this but it logs the input price immediately instead of checking the condition first and then waiting for the condition to be met first before logging. Below is the Code:
//Datafetching
import React, {createContext, useState, useEffect}from 'react'
import {ActivityIndicator} from 'react-native'
import axios from '../utils/axios'
const CurrencyContext = createContext();
const CurrencyProvider =(props) => {
const [data, setData] = useState([])
const [isLoading, setIsloading] = useState(true)
useEffect(() => {
const interval = setInterval(() => {
const fetchpairs = async() => {
const results = await axios.get('/v3/accounts/101-004-14328428-002/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')
setData(results.data)
setIsloading(false)
}
fetchpairs()
},1000)
}, []);
if(isLoading) {
return (
<ActivityIndicator size="large"/>
)
}else
return (
<CurrencyContext.Provider
value={{
data,
setData,
isLoading,
setIsloading
}}>
{props.children}
</CurrencyContext.Provider>
)
}
export {CurrencyProvider, CurrencyContext}
//HomeScreen
import React, {useContext, useState, useEffect} from 'react'
import { Text, View, ScrollView, TouchableOpacity, Modal, TextInput, ToastAndroid, Picker, Alert } from 'react-native'
import {ListItem, Card, Button, Icon} from 'react-native-elements'
import {ActionSheet} from 'native-base'
//import CurrencyPair from '../../CurrencyPair'
import {firebase} from '../../../firebase/config'
import {CurrencyContext} from '../../../context/Context'
import styles from '../HomeScreen/styles'
function HomeScreen({navigation, props}) {
const currency = useContext(CurrencyContext);
//hook for the modal
const [modalopen, setModalOpen] = useState(false)
//hook for the clicked currency pair
const [clickedindex, setClickedIndex] = useState(0)
//hook for the actionsheet
const[sheet, setSheet] = useState(null)
//Hooks for the alert
const [pricealert, setPricealert] = useState('')
//function for checking alert condition
const checkAlertCondition = (pricealert) => {
if(pricealert >= {...currency.data.prices[clickedindex].closeoutAsk} ){
setPricealert(pricealert)
console.log("Price" + pricealert + "has been hit")
}
else if(pricealert <= {...currency.data.prices[clickedindex].closeoutAsk})
{
setPricealert(pricealert)
console.log("Price" + pricealert + "has been hit")
}
else
{
console.log("Set your alert price")
}
}
//toast method that will be called when the ok button is called
const showToastWithGravityAndOffset = () => {
ToastAndroid.showWithGravityAndOffset(
"Alert created successfully",
ToastAndroid.SHORT,
ToastAndroid.BOTTOM,
25,
50
);
};
const BUTTONS = [
{ text: "SMS", icon: "chatboxes", iconColor: "#2c8ef4" },
{ text: "Email", icon: "analytics", iconColor: "#f42ced" },
{ text: "Push Notification", icon: "aperture", iconColor: "#ea943b" },
{ text: "Delete", icon: "trash", iconColor: "#fa213b" },
{ text: "Cancel", icon: "close", iconColor: "#25de5b" }
];
const DESTRUCTIVE_INDEX = DESTRUCTIVE_INDEX;
const CANCEL_INDEX = CANCEL_INDEX;
return (
<ScrollView>
<Modal
visible={modalopen}
animationType={"fade"}
>
<View style={styles.modal}>
<View>
<Text style={{textAlign: "center", fontWeight: "bold"}}>
{currency.data.prices[clickedindex].instrument}
</Text>
<Text style={{textAlign: "center"}}>
{currency.data.prices[clickedindex].closeoutAsk}/{currency.data.prices[clickedindex].closeoutBid}
</Text>
<Card.Divider/>
<View style={{ flexDirection: "row"}}>
<View style={styles.inputWrap}>
<TextInput
style={styles.textInputStyle}
value={pricealert}
onChangeText = {(pricealert) => setPricealert(pricealert)}
placeholder="Alert Price"
placeholderTextColor="#60605e"
numeric
keyboardType='decimal-pad'
/>
</View>
<View style={styles.inputWrap}>
</View>
</View>
<TouchableOpacity
onPress={() =>
ActionSheet.show(
{
options: BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
destructiveButtonIndex: DESTRUCTIVE_INDEX,
title: "How do you want to receive your notification"
},
buttonIndex => {
setSheet({ clicked: BUTTONS[buttonIndex] });
}
)}
style={styles.button}
>
<Text>ActionSheet</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button}
onPress={() => {setModalOpen(false); checkAlertCondition(pricealert);showToastWithGravityAndOffset();} }>
<Text style={styles.buttonTitle}>OK</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
<Card>
<Text style={{textAlign: "center"}}>
Welcome
</Text>
<Button title="Sign Out" type="outline" onPress ={() => firebase.auth().signOut()}/>
<Button title="My Alerts" onPress ={() =>navigation.navigate("AlertScreen") }/>
</Card>
<View>
{currency.data.prices && currency.data.prices.map((prices, index) => {
return (
<ListItem
key={index}
onPress = {() => {setModalOpen(true);setClickedIndex(index);}}
bottomDivider>
<ListItem.Content>
<ListItem.Title>
{currency.data.prices[index].instrument} {currency.data.prices[index].closeoutAsk} {currency.data.prices[index].closeoutBid}
</ListItem.Title>
</ListItem.Content>
</ListItem>
)
})
}
</View>
</ScrollView>
)
}
export default HomeScreen
inside onPress you are calling checkAlertCondition but with no params yet inside that function you are expecting the pricealert also you are trying to use >= with the left hand side being an object.
Try this:
const checkAlertCondition = (pricealert) => {
if(currency.data.prices[clickedindex].AskPrice >= pricealert){
setPricealert(pricealert)
console.log("Price" + pricealert + "has been hit")
}
}
I updated my code thanks to your help.
When I launch the app with Expo, the opening works but I lost my scan icon which does not appear in my screen.
This icon appeared previously.
The idea is to scan some barcodes in order to display relevant data stemming from products.
Here is my new code:
import React, { useState, useEffect } from "react";
import {
StyleSheet,
Text,
View,
FlatList,
Button,
AsyncStorage,
} from "react-native";
import { useNavigation } from "#react-navigation/core";
import { TouchableOpacity } from "react-native-gesture-handler";
import { FontAwesome5 } from "#expo/vector-icons";
import { MaterialCommunityIcons } from "#expo/vector-icons";
import { ActivityIndicator } from "react-native-paper";
function ProductsScreen() {
const navigation = useNavigation();
const [data, setData] = useState([]);
const [isLoading, setisLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
const data = await AsyncStorage.getItem("userData");
setData(data);
setisLoading(false);
};
fetchData();
}, []);
console.log(data);
return isLoading ? (
<ActivityIndicator />
) : (
<>
{data ? (
<FlatList
data={dataArray}
keyExtractor={(item) => item.name}
renderItem={({ item }) => (
<>
<Text>{item.brand}</Text>
<View style={styles.scan}>
<MaterialCommunityIcons
name="barcode-scan"
size={40}
color="black"
onPress={() => {
navigation.navigate("CameraScreen");
}}
/>
</View>
</>
)}
/>
) : null}
</>
);
}
export default ProductsScreen;
I would appreciate your comments please.
You could use ? (optional chaining) to confirm data doesnt yield to undefined before mapping.
data?.map((data, index) => {return <>....</>}
You need to return from data.map function to render the array items
return isLoading ? (
<ActivityIndicator />
) : (
<>
{data?.map((data, index) => {
return <View key ={index}>
<Text> {data.products_name_fr} </Text>
<Text> {data.brands} </Text>
<Text> {data.image_url} </Text>
<View style={styles.scan}>
<MaterialCommunityIcons
name="barcode-scan"
size={40}
color="black"
onPress={() => {
navigation.navigate("CameraScreen");
}}
/>
</View>
</View>;
})}
</>
);
Or short-hand of return
return isLoading ? (
<ActivityIndicator />
) : (
<>
data?.map((data, index) => (
<View key ={index}>
<Text> {data.products_name_fr} </Text>
<Text> {data.brands} </Text>
<Text> {data.image_url} </Text>
<View style={styles.scan}>
<MaterialCommunityIcons
name="barcode-scan"
size={40}
color="black"
onPress={() => {
navigation.navigate("CameraScreen");
}}
/>
</View>
</View>;
))
</>
);
I changed my code like this but I have the same error. Besides, the part of code which begins from: const styles=Stylesheet.create seems to be not active
import React, { useState, useEffect } from "react";
import { StyleSheet, Text, View, Button, AsyncStorage } from "react-native";
import { useNavigation } from "#react-navigation/core";
import { TouchableOpacity } from "react-native-gesture-handler";
import { FontAwesome5 } from "#expo/vector-icons";
import { MaterialCommunityIcons } from "#expo/vector-icons";
import { ActivityIndicator } from "react-native-paper";
import axios from "axios";
function ProductsScreen() {
const navigation = useNavigation();
const [data, setData] = useState([]);
const [isLoading, setisLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
const data = await AsyncStorage.getItem("userData");
setisLoading(false);
setData(data);
};
fetchData();
}, []);
return isLoading ? (
<ActivityIndicator />
) : (
<>
{data?.map((data, index) => {
return (
<>
key ={index}
<Text> {data.products_name_fr} </Text>
<Text> {data.brands} </Text>
<Text> {data.image_url} </Text>
<View style={styles.scan}>
<MaterialCommunityIcons
name="barcode-scan"
size={40}
color="black"
onPress={() => {
navigation.navigate("CameraScreen");
}}
/>
</View>
</>
);
})}
</>
);
const styles = StyleSheet.create({
products: {
alignItems: "center",
justifyContent: "center",
},
scan: {
marginLeft: 30,
position: "absolute",
bottom: 0,
right: 20,
marginBottom: 60,
marginRight: 30,
padding: 10,
borderRadius: 10,
backgroundColor: "#ff9234",
},
});
}
export default ProductsScreen;
I changed a little bit my code and I got another type of error : Invariant violation: Text strings must be rendered within a component. I will really appreciate your comments and support to fix this
return isLoading ? (
<ActivityIndicator />
) : (
<>
data?.map((data, index) => (
<>
<Text> {data.products_name_fr} </Text>
<Text> {data.brands} </Text>
<Text> {data.image_url} </Text>
<View style={styles.scan}>
<MaterialCommunityIcons
name="barcode-scan"
size={40}
color="black"
onPress={() => {
navigation.navigate("CameraScreen");
}}
/>
</View>
</>
))
</>
);
}
In the useEffect, set the data as array. Example
const = [data, setData] = useState([]); // do this in your state
setData([data]); //do this in your useEffet hook
I just started to learn React-native. In this app I have a two buttons in header, first 'Todo', second 'Tags'. I want to chang content by press on these buttons. I think I need to change state.for clarityWhat I mean, when i tap on the button Tags, below I get TagScreen component, exactly the same for the button Todo. How to connect these components so that they work correctly?
app.js
import React, { useState } from 'react'
import { StyleSheet, View, FlatList } from 'react-native'
import { Navbar } from './src/Navbar'
import { TagScreen } from './src/screens/TagScreen'
import { TodoScreen } from './src/screens/TodoScreen'
export default function App() {
const [todos, setTodos] = useState([])
const [tags, setTags] = useState([])
const [appId, setAppId] = useState([])
const addTodo = title => {
setTodos(prev => [
...prev,
{
id: Date.now().toString(),
title
}
])
}
const addTags = title => {
setTags(prev => [
...prev,
{
id: Date.now().toString(),
title
}
])
}
const removeTags = id => {
setTags(prev => prev.filter(tag => tag.id !== id))
}
const removeTodo = id => {
setTodos(prev => prev.filter(todo => todo.id !== id))
}
return (
<View>
<Navbar title='Todo App!' />
<View style={styles.container}>
<TagScreen addTags={addTags} tags={tags} removeTags={removeTags}/>
{/* <TodoScreen todos={todos} addTodo={addTodo} removeTodo={removeTodo} /> */}
{/* HERE MUST CHANGED COMPONENTS */}
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
paddingHorizontal: 30,
paddingVertical: 20
}
})
navbar.js
import React from 'react'
import { View, Text, StyleSheet, Button, TouchableOpacity } from 'react-native'
export const Navbar = ({ title }) => {
return (
<View style={styles.padding}>
<View style={styles.navbar}>
<TouchableOpacity
style={styles.button}
>
<Text>Todo</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
>
<Text>Tags</Text>
</TouchableOpacity>
<Text style={styles.text}>{title}</Text>
</View>
</View>
)
}
well you need to track the visiblity of what is visible in your state,
in your App component, do this;
const [showTodos, setShowTodos] = useState(false);
const makeTodosInvisible= () => setShowTodos(false);
const makeTodosVisible = () => setShowTodos(true);
return (
<View>
<Navbar onTodoPress={makeTodosVisible } onTagPress={makeTodosInvisible} title='Todo App!' />
<View style={styles.container}>
{showTodos
? <TodoScreen todos={todos} addTodo={addTodo} removeTodo={removeTodo} />
: <TagScreen addTags={addTags} tags={tags} removeTags={removeTags}/>
}
{/* <TodoScreen todos={todos} addTodo={addTodo} removeTodo={removeTodo} /> */}
{/* HERE MUST CHANGED COMPONENTS */}
</View>
</View>
)
and in your navbar.js do this
export const Navbar = ({ title, onTodoPress, onTagPress}) => {
return (
<View style={styles.padding}>
<View style={styles.navbar}>
<TouchableOpacity
style={styles.button}
onPreesed={onTodoPress} // will hide Tags and show Todos
>
<Text>Todo</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPreesed={onTagPress} // will show Tags and hide Todos
>
<Text>Tags</Text>
</TouchableOpacity>
<Text style={styles.text}>{title}</Text>
</View>
</View>
)
}