I am a newbie in react native, I am developing a video app to aid my learning curve. In the code below I have tried all I could to solve the error on the "displayModal" line, but could not. Please can anyone help me with this.
I want on image/video capture it will display on the modal and from the modal i will be able to "Discard", or "Save"(to firebase), or "Share" the image/video.
import React from 'react';
import { View, Text, Image, Modal, TouchableOpacity } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import styles from './styles';
export default ({captures=[]}) => {
state = {
isVisible: false
}
// hide show modal
displayModal(show){ ------this is where am getting the error
this.setState({isVisible: show})
}
return (
<Modal
transparent={true}
visible={this.state.isVisible}
// style={[styles.bottomToolbar, styles.galleryContainer]}
>
<View style={{backgroundColor: "#000000aa", flex: 1}}>
{captures.map(({ uri }) => (
<View style={styles.galleryImageContainer} key={uri}>
<Image source={{ uri }} style={styles.galleryImage} />
</View>
))}
</View>
<TouchableOpacity style={{justifyContent: 'center', alignItems: 'center'}}>
<Ionicons
name="close-outline"
color="white"
size={20}
onPress={() => {this.displayModal(!this.state.isVisible);}}
/>
<Text>Discard</Text>
</TouchableOpacity>
</Modal>
);
};
click here to see error image
From you code it looks like a functional component, but you are using state as class-based component, that might be the reason you are getting error :
export default ({captures=[]}) => {
state = {
isVisible: false
}
// hide show modal
displayModal(show){ ------this is where am getting the error
this.setState({isVisible: show})
}
Above code block should look like this :
export default ({captures=[]}) => {
const [state,setState] = useState({ isVisible: false })
// hide show modal
const displayModal = (show) => {
setState({isVisible: show})
}
You are mixing functional component with class component.
"this.state" and "this.setState" belong to class components and all the rest belongs to functional components.
Try to change this:
state = {
isVisible: false
}
// hide show modal
displayModal(show){ ------this is where am getting the error
this.setState({isVisible: show})
}
To this:
const [isVisible, setIsVisible] = React.useState(false);
const displayModal = show => setIsVisible(show);
In addition, in the return statement, remove the strings/words "this" and "this.state".
Requested addition:
import React, { useState } from 'react';
import { View, Text, Image, Button, Modal, TouchableOpacity } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import { storage } from './fbstorage';
import { Camera } from 'expo-camera';
import styles from './styles';
export default ({ captures = [] }) => {
const [isVisible, setIsVisible] = useState(false);
const takePicture = async () => {
const photoData = await Camera.takePictureAsync();
if (!photoData.cancelled) {
uploadImage(photoData.uri, imageName)
.then(() => {
Alert.alert("Success");
})
.catch((error) => {
Alert.alert('Error:', error.message);
});
}
}
const uploadImage = async (uri, imageName) => {
const response = await fetch(uri);
const blob = await response.blob();
var ref = storage().ref().child("images/" + imageName);
return ref.put(blob)
}
return (
<Modal
transparent={true}
visible={isVisible}
// style={[styles.bottomToolbar, styles.galleryContainer]}
>
<View style={{ backgroundColor: "#000000aa", flex: 1 }}>
{captures.map(({ uri }) => (
<View style={styles.galleryImageContainer} key={uri}>
<Image source={{ uri }} style={styles.galleryImage} />
</View>
))}
</View>
<TouchableOpacity
style={{
justifyContent: 'center',
alignItems: 'center',
marginTop: 20,
top: -20
}}
onPress={() => setIsVisible(false)}
>
<Ionicons
name="md-reverse-camera"
color="white"
size={40}
/>
<Text style={{ color: 'white' }}>Discard</Text>
</TouchableOpacity>
<Button
title='Save'
onPress={takePicture}
/>
</Modal>
);
};
Related
I am doing a project using MERN STACK in this I faced the above error.
ProductContainer.js
import React, { useState, useEffect } from 'react'
import { View, StyleSheet, ActivityIndicator, FlatList, Text} from 'react-native'
import { Container, Header, Icon, Item, Input } from 'native-base';
import ProductList from './ProductList';
import SearchedProduct from './SearchedProducts';
const data = require('../../assets/data/products.json');
const ProductContainer = () => {
const [products, setProducts ] = useState([]);
const [productsFiltered, setProductsFiltered] = useState([]);
const [focus, setFocus] = useState();
useEffect(() => {
setProducts(data);
setProductsFiltered(data);
setFocus(false);
return () => {
setProducts([])
setProductsFiltered([])
setFocus()
}
}, [])
const SearchProduct = (text) => {
setProductsFiltered(
products.filter((i) => i.name.toLowerCase().includes(text.toLowerCase()))
);
};
const openList = () => {
setFocus(true);
};
const onBlur = () => {
setFocus(flase);
};
return (
<Container>
<View style = {{ flexDirection: "row"}}>
<Input
width = "100%"
variant = "rounded"
placeholder="Search"
onFocus={openList}
onChangeText={(text) => SearchProduct(text)}
/>
</View>
{focus == true ? (
<SearchProduct
productsFiltered={productsFiltered}
/>
) : (
<View style={styles.container}>
<Text>Product Container</Text>
<View style={styles.listContainer}>
<FlatList
data={products}
numColumns={2}
renderItem={({item}) => <ProductList
key={item.brand}
item={item}/>}
keyExtractor={item => item.brand}
/>
</View>
</View>
)}
</Container>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
export default ProductContainer
SearchedProducts.js
import React from 'react';
import { View, StyleSheet, Dimensions} from 'react-native'
import { Content, Left, Body, ListItem, Thumbnail, Text } from 'native-base';
const SearchedProduct = (props) => {
const { productsFiltered } = props;
return(
<Content >
{productsFiltered.length > 0 ? (
productsFiltered.map((item) => (
<ListItem
key={item._id.$oid}
avatar
>
<Left>
<Thumbnail
source={{uri: item.image ?
item.image : 'https://cdn.pixabay.com/photo/2012/04/01/17/29/box-23649_960_720.png'
}}
/>
</Left>
<Body>
<Text>{item.name}</Text>
<Text note>{item.description}</Text>
</Body>
</ListItem>
))
) : (
<View style={styles.center}>
<Text style={{ alignSelf: 'center' }}>
No products match the selected criteria
</Text>
</View>
)}
</Content>
);
};
const styles = StyleSheet.create({
center: {
justifyContent: 'center',
alignItems: 'center',
height: 100
}
})
export default SearchedProduct;
Please can anyone help me to solve this error .If you want I will provide other details of my code.
Thanks in advance
Not sure but you are using SearchProduct name as a component and at the same time as a method. Maybe try to rename changing either component name or method name to see if it works.
I'm using redux toolkit to manage state and am finding that the components are not updating when changes are made to the state.
I do see though, that when I listen to changes in my redux state within a useEffect that it will trigger the callback, meaning it is aware that the redux state has changed but the component is not rerendering.
Reading other questions it seems like a lot of the issues were about mutating the state, but I do know that using redux tool kit allows you to write "mutable" code and this is handled by Immer. Not sure if this is an issue that applies here...
My Slice:
const initialState = {
watchlists: []
}
export const watchlistsSlice = createSlice({
name: 'watchlists',
initialState,
reducers: {
updateWatchlists: (state, { payload }) => {
state.watchlists = payload;
},
},
})
export const { updateWatchlists } = watchlistsSlice.actions;
export default watchlistsSlice.reducer;
This is the component that calls the function that changes the state:
import React from 'react';
import { StyleSheet, View, Image } from 'react-native';
import { useSelector, useDispatch } from 'react-redux';
import Text from '../core/Text';
import Pressable from '../core/Pressable';
import { AddIcon } from '../core/Icons';
import { formatPrice, formatPercent } from '../../utils/formatNumber';
import { shortenLongText } from '../../utils/formatText';
import { updateWatchlists } from '../../redux/watchlistsSlice';
import { addToWatchlist } from '../../storage/watchlists';
export default function ListItem({data, theme, navigation, watchlistID }) {
const dispatch = useDispatch();
const { currency } = useSelector(state => state.userPreference)
const addCryptoToWatchlist = async () => {
if (watchlistID) {
addToWatchlist(watchlistID, {
slug: data.slug,
})
.then(result => dispatch(updateWatchlists(result)))
.catch(err => console.log(err))
} else {
console.log('not ready yet')
}
}
return (
<Pressable
onPress={() => navigation.navigate('CoinDetails', {
data,
})}
>
<View style={styles.searchResult}>
<View style={styles.nameContainer}>
<Image style={styles.image} source={{uri: data.logo}} />
<View style={{marginLeft: 15}}>
<Text type={"big"} size={18} theme={theme.text}>{data.symbol}</Text>
<Text type={"regular"} size={14} theme={theme.text} style={{paddingTop: 1}}>{shortenLongText(data.name,25)}</Text>
</View>
</View>
<View style={styles.rightContainer}>
<View style={styles.priceContainer}>
<Text type={"big"} theme={theme.text}>{formatPrice(data.price, currency)}</Text>
<Text type={"big"} theme={data.direction === 'up' ? theme.percent.up : theme.percent.down}>{formatPercent(data.percent_change_24h)}</Text>
</View>
<Pressable onPress={() => addCryptoToWatchlist()}>
<AddIcon
size={30}
/>
</Pressable>
</View>
</View>
</Pressable>
)
}
const styles = StyleSheet.create({
searchResult: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 30,
},
nameContainer : {
flexDirection: 'row',
alignItems: 'center',
},
rightContainer: {
flexDirection: 'row',
alignItems: 'center',
},
priceContainer: {
alignItems: 'flex-end',
marginRight: 20
},
image: {
width: 28,
height: 28,
}
})
This is one the components that I expect to rerender when the state changes:
The useEffect does get trigged so the component is recognizing a change in state, but the component does not rerender.
I dont know if this is insightful, but the data in the state is an array of objects and in this case a single property one of the objects is getting changed.
import React, { useState, useEffect } from 'react';
import { View, StyleSheet } from 'react-native';
import { useSelector } from 'react-redux';
import GetStarted from './GetStarted';
import AddCryptoCard from './AddCryptoCard';
import CardList from './CardList';
import Text from '../core/Text';
export default function WatchlistCardsSection({ setModalVisible, navigation }) {
const { theme } = useSelector(state => state.userPreference);
const { watchlists } = useSelector(state => state.watchlists)
const { cryptoData } = useSelector(state => state.cryptoData);
const [ watchlistCryptoDataLoaded, setWatchlistCryptoDataLoaded ] = useState(false);
const checkIfWatchlistDataLoaded = () => {
const watchlistNames = watchlists.map(watchlist => watchlist.name);
const checkIfLoaded = cryptoData.map(data => watchlistNames.some(name => data.tags.includes(name))).includes(true);
setWatchlistCryptoDataLoaded(checkIfLoaded);
}
useEffect(() => {
checkIfWatchlistDataLoaded();
},[cryptoData])
useEffect(() => console.log("watchlist updated"), [watchlists])
return (
watchlists &&
watchlists.length === 0 ?
<GetStarted
setModalVisible={setModalVisible}
/>
:
watchlists.filter(item => item.viewOnHome).map(watchlist => (
watchlist.data.length === 0 ?
<AddCryptoCard
key={watchlist.id}
id={watchlist.id}
name={watchlist.name}
navigation={navigation}
/>
:
watchlistCryptoDataLoaded ?
<View
key={watchlist.id}
style={styles.sectionContainer}
>
<Text style={{paddingLeft: 20}} type={'big'} size={24} theme={theme.text}>{watchlist.name}</Text>
<CardList
name={watchlist.name}
config={{type: 'price'}}
navigation={navigation}
/>
</View>
: null
))
)
}
const styles = StyleSheet.create({
sectionContainer: {
flex: 1,
marginTop: 25,
}
})
I am new to React Native and I am trying to create an application with it.
The problem is when I try to display the data in the application.
I am trying to consume a REST API to be able to display the data but it is not showing me anything.
Besides this it does not show me what the error is so I am confused.
I think it's like I'm consuming the API but I can't find the error.
This would be my code:
import { StatusBar } from 'expo-status-bar';
import React, { useEffect, useState, useContext } from 'react';
import { StyleSheet, Text, View, FlatList, Image} from 'react-native';
const MORE_ICON = Platform.OS === 'ios' ? 'dots-horizontal' : 'dots-vertical';
import { Appbar } from 'react-native-paper';
import { Platform } from 'react-native';
import { Searchbar } from 'react-native-paper';
import { Avatar, Button, Card, Title, Paragraph } from 'react-native-paper';
import { render } from 'react-dom';
const API_ENDPOINT = 'https://localhost:5001/api/Medicines/';
export default function App () {
const [searchQuery, setSearchQuery] = React.useState('');
const onChangeSearch = query => setSearchQuery(query);
const [data, setData] = useState([]);
const [error, setError] = useState(null);
useEffect(() => {
fetch(API_ENDPOINT)
.then(response => response.json())
.then(results => {
setData(results);
})
.catch(err => {
setError(err);
});
}, []);
return (
<View >
<Appbar.Header>
<Appbar.Content title=" Medicine" />
</Appbar.Header>
<Searchbar
placeholder="Search"
onChangeText={onChangeSearch}
value={searchQuery}
/>
<FlatList
data={data}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<Card>
<Card.Content>
<Title>{`${item.name.id}`}</Title>
<Paragraph></Paragraph>
</Card.Content>
<Card.Cover />
<Card.Actions>
<Button>info</Button>
</Card.Actions>
</Card>
)}
/>
</View>
)
}
UPDATE
Add two if conditions, each returning a JSX for two different scenarios. First, when the data is fetched, a loading indicator is displayed. Second, when there is an error, an error message is displayed.
But it shows me the scenario of the error "Error fetching data... Check your network connection!"
export default function App() {
// state variables defined
// fetch data using useEffect
if (isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" color="#5500dc" />
</View>
);
}
if (error) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ fontSize: 18}}>
Error fetching data... Check your network connection!
</Text>
</View>
);
}
// ...
}
So I have a an image selector that when I press, it launches the phone image library and then when I select the image it is supposed to fill that image selector but every time i select an image, I get this error
[TypeError: undefined is not an object (evaluating 'iter[Symbol.iterator]')]
This is how my code looks like this is the App file
import React, {useState} from 'react'
import { Button, StyleSheet, Text, View } from 'react-native'
import Screen from './app/components/Screen'
import ImageInputList from './app/components/ImageInputList'
export default function App() {
const [imageUris, setImageUris] = useState();
const handleAdd = (uri) => {
setImageUris([...imageUris, uri])
}
const handleRemove = uri => {
setImageUris(imageUris.filter(imageUri => imageUri !== uri))
}
return (
<Screen>
<ImageInputList imageUris={imageUris} onAddImage={handleAdd} onRemoveImage={handleRemove} />
</Screen>
)
}
And then this is my 2nd component the "imageInputList"
import React from 'react'
import { StyleSheet, Text, View } from 'react-native'
import ImageInput from './ImageInput'
export default function ImageInputList({imageUris = [], onRemoveImage, onAddImage}) {
return (
<View style={styles.container}>
{imageUris.map((uri) => (
<View key={uri} style={{marginRight: 10}}>
<ImageInput
imageUri={uri}
onChangeImage={() => onRemoveImage(uri)}
/>
</View>
))}
<ImageInput onChangeImage={(uri) => onAddImage(uri)} />
</View>
)
}
And lastly, this is the imageInput component
import React, {useEffect} from 'react'
import { Image, StyleSheet, TouchableWithoutFeedback, Alert, View } from 'react-native'
import {MaterialCommunityIcons} from "#expo/vector-icons"
import * as ImagePicker from "expo-image-picker"
export default function ImageInput({imageUri, onChangeImage}) {
useEffect(() => {
requestPermission();
}, [])
const requestPermission = async () => {
const {granted} = await ImagePicker.requestMediaLibraryPermissionsAsync();
if(!granted) alert("Allow this app to access your image library")
}
const handlePress = () => {
if(!imageUri) selectImage();
else Alert.alert("Delete",
"Are you sure you want to delete this image?",
[{text: "Yes", onPress: onChangeImage(null)}, {text: "No"},])
};
const selectImage = async () => {
try {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
quality: 0.5,
});
if(!result.cancelled) onChangeImage(result.uri);
}
catch (error) {
console.log("Something went wrong in your code", error)
}
}
return (
<TouchableWithoutFeedback onPress={handlePress}>
<View style={styles.container} >
{!imageUri && <MaterialCommunityIcons name="camera" size={40} color="grey" />}
{imageUri && <Image source={{uri: imageUri}} style={styles.image} />}
</View>
</TouchableWithoutFeedback>
)
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#f1f1f1",
borderRadius: 15,
marginTop: 40,
alignItems: 'center',
justifyContent: 'center',
overflow: "hidden",
width: 100,
height: 100,
},
image: {
height: "100%",
width: "100%",
}
})
I know the issue has something to do with "handleAdd" or the "onChangeImage" part but I do not know exactly how to fix them. Thanks in Advance.
The problem is here:
const [imageUris, setImageUris] = useState();
You're trying to spread imageUris but it is not an array when it is first initialized.
Simply replace useState(); with useState([]);
I have a TextInput, and have a function named onEnterPin.
But i just couldnt reach that value. All I want is to get the value inside TextInput, and navigate to another screen if the value inside TextInput is correct
Could you help me? Btw one more question: After the pin is correct, i navigate to Home screen, and on Home screen I should have rooms(like living room etc, and items(tv, internet etc) under the room name and picture. Could you give me hint?
Here is the code
import React, { useState } from "react";
import { Text, View, Button, StyleSheet, TextInput, Alert } from "react-native";
const SplashScreen = ({ navigation }) => {
const [pin, setPin] = useState('');
const CORRECT_PIN = "5555";
const onEnterPin = (pin)=>{
if(pin === CORRECT_PIN) {
navigation.navigate("Home");
}
else{
Alert.alert("problem here")
}
};
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Welcome to Rooms Page</Text>
<Button
title="Go to HomeScreen"
onPress = {() => {
navigation.navigate("Home", {
itemId: 86,
otherParam: "anything you want here"
});
}} // go to the screen named Home
/>
<Text>PIN gir</Text>
<TextInput value={pin} style={styles.textInput} onChangeText={pin => setPin(pin)}></TextInput>
<Button
title="Enter"
onPress = {() => {
onEnterPin(value); // i guess the problem is here, what should i write
}}
/>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#307ecc',
},
textInput: {
borderWidth:.5,
height:35,
margin:12,
}
});
export default SplashScreen;
HomeScreen.js
import React from "react";
import { View, Text, Button } from "react-native";
const HomeScreen = ({ route, navigation }) => {
const { itemId } = route.params;
const { otherParam } = route.params;
return(
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go back"
onPress = {() => navigation.goBack()}
/>
<Button
title="go to example screen"
onPress={() => navigation.navigate("Example")}
/>
<Button
title="go to Home page again, using push"
onPress = {() => {
navigation.push("Home", {
itemId: Math.floor(Math.random() * 100)
}),
navigation.setParams({itemId:200}) // it updates itemId as 200, then does random number job in Math.random()
}}
/>
</View>
// Avoid using setParams to update screen options such as title etc. If you need to update options, use setOptions instead.
)
}
export default HomeScreen;
Change onEnterPin parameter from value to pin like this:
<Button
title="Enter"
onPress = {() => {
onEnterPin(pin); // <<<<<<<<<<<<<<<<
}}
/>
my Textinput has an ID and with this we can do this:
document.getElementById(id).value
to get the value of the Input.
You don't need to pass it to a function since the pin value already exists in local state:
const onEnterPin = () => {
if (pin === CORRECT_PIN) {
navigation.navigate("Home");
}
else {
Alert.alert("problem here")
}
};
and:
<TextInput value={pin} style={styles.textInput} onChangeText={setPin} />
<Button
title="Enter"
onPress={onEnterPin}
/>
As the 'pin' variable exists as a local state, you can use it in the 'onEnterPin()' method, without using a parameter.
The 'onEnterPin' method will be as:
const onEnterPin = () => {
if(pin === CORRECT_PIN) {
navigation.navigate("Home")
}
else{
Alert.alert("problem here")
}
}