react native modal not close after setState false - react-native

I have set modal visibility to false but it still showing. I cant figure out what causes this issue. this my code at loading.js.
I'm use this component in main what happen when setState false but its just close after close simolator and restart the device
import React,{Component} from 'react';
import PropTypes from 'prop-types'
import {View, Image, Modal, StyleSheet, Text} from "react-native";
export default class Loader extends Component{
render(){
const {animationType,modalVisible}=this.props;
return(
<Modal
animationType={animationType}
transparent={true}
visible={modalVisible}>
<View style={styles.wrapper}>
<View style={styles.loaderContainer}>
<Image
source={require('../img/loading.gif')}
style={styles.loaderImage}/>
</View>
</View>
</Modal>
)
}
}
Loader.propTypes={
animationType:PropTypes.string.isRequired,
modalVisible:PropTypes.bool.isRequired
}
this main class
export default class ForoshRah extends Component {
constructor() {
super();
I18nManager.forceRTL(true);
this.state = {
image: null,
images: null,
loadingVisible:false,
};
this.onValueChange2=this.onValueChange2.bind(this);
this.OnSubmiteData=this.OnSubmiteData.bind(this);
}
onValueChange2(value: string) {
this.setState({
Field: value,
});
}
async OnSubmiteData(){
this.setState({loadingVisible:true})
let token = await AsyncStorage.getItem('token',token);
let response = await
fetch(url,{
method:'POST',
headers:{
'Content-Type':'application/json',
Authorization:'JWT'+" "+token,
}
,body: JSON.stringify({
title,
})
})
let register = await response.json();
this.setState({userID:register.id})
if(response.status===200){
this.UploadImage()
}
}
async UploadImage() {
let token = await AsyncStorage.getItem('token',token);
let response = await fetch(url,{
method:'POST',
headers:{
Authorization:'JWT'+" "+token,
},body: formData
})
let uimage = await response;
console.log('user',this.state.userID);
if(response.status=200){
handleCloseModal = () => {
console.log(this.state.loadingVisible);
this.setState({ loadingVisible: false})
});
};
this.props.navigation.dispatch({ type: 'Navigation/BACK' })
}else {
setTimeout(() => {
this.setState({ loadingVisible: false })
}, 100)
}
setTimeout(() => {
this.setState({ loadingVisible: false })
}, 100)
}
render() {
return (
<KeyboardAwareScrollView >
<View style={{marginBottom:'10%'}}>
<Button block style={{backgroundColor:'#8e25a0'}} onPress={this.OnSubmiteData.bind(this)}>
</Button>
</View>
<Loader
modalVisible={loadingVisible}
animationType="fade"
/>
</KeyboardAwareScrollView>
);
}
}
onsubmitdata setState true and after response going to 200 Setstate set false in code main

You cannot just call state name as you have did. You should do like below.
<Loader
modalVisible={this.state.loadingVisible}
animationType="fade"
/>

Related

Expo : I want to render a Modal every x minutes

I want to render A modal every X minutes , so i tried to cache a value in AsyncStorage that gets removed every x minutes , and depends on the value i want to render the modal , but when my app is refreshed the modal appears again , here's what i have done :
import AsyncStorage from "#react-native-async-storage/async-storage";
import moment from "moment";
const prefix = "cache";
const expiryInMinutes = 5;
const store = async (key, value) => {
try {
const item = {
value,
timestamp: Date.now(),
};
await AsyncStorage.setItem(prefix + key, JSON.stringify(item));
} catch (error) {
console.log(error);
}
};
const isExpired = (item) => {
const now = moment(Date.now());
const storedTime = moment(item.timestamp);
return now.diff(storedTime, "minutes") > expiryInMinutes;
};
const get = async (key) => {
try {
const value = await AsyncStorage.getItem(prefix + key);
const item = JSON.parse(value);
if (!item) return null;
if (isExpired(item)) {
await AsyncStorage.removeItem(prefix + key);
return null;
}
return item.value;
} catch (error) {
console.log(error);
}
};
export default {
store,
get,
};
Then i have this component that i want to render every X minutes :
import React, { Component } from "react";
import { Text, TouchableOpacity, StyleSheet, View } from "react-native";
import Modal from "react-native-modal";
import AsyncStorage from "#react-native-async-storage/async-storage";
import cache from "../utility/cache";
export default class PubGlobal extends Component {
state = {
visibleModal: "false",
};
componentDidMount() {
cache.get("shown").then(
this.setState({
visibleModal: "true",
})
);
}
_renderButton = (text, onPress) => (
<TouchableOpacity onPress={onPress}>
<View style={styles.button}>
<Text>{text}</Text>
</View>
</TouchableOpacity>
);
_renderModalContent = () => (
<View style={styles.modalContent}>
<Text>Hello! </Text>
{this._renderButton("Close", () =>
cache
.store("shown", "false")
.then(this.setState({ visibleModal: "false" }))
)}
</View>
);
isShown = async () => {
try {
const stored = await cache.get("shown");
this.setState({ visibleModal: stored });
console.log(this.state.visibleModal);
} catch (error) {
console.log(error);
}
};
render() {
return (
<View style={styles.container}>
{/* {this._renderButton("Default modal", () =>
this.setState({ visibleModal: "true" })
)} */}
{this.state.visibleModal && (
<Modal isVisible={this.state.visibleModal === "true"}>
{this._renderModalContent()}
</Modal>
)}
</View>
);
}
}
In componentDidMount, after getting the value, visibleModal is set to "true".
You should use the value you are getting when cache.get("shown") resolves.
componentDidMount() {
cache.get("shown").then(
this.setState({
visibleModal: "true",
})
);
}

"Undefined is not an object" when trying to access state in react native

So basically I have the input form "Vin Number" here
<InputX
label="Vin Number"
style={{backgroundColor: '#fafafa'}}
autoCapitalize="none"
returnKeyType={'next'}
key="uemail"
onChangeText={text => this.setState({currentTypedVin: text})}
/>
and I am using
onChangeText={text => this.setState({currentTypedVin: text})}
to set the state of currentTypedVin to the text that is added into the input. I am then trying to access that state in the GetReport function here
let vinNumb = this.state.currentTypedVin;
However for some reason I am getting the error "Undefined is not an object (evaluating this.state.currentTypedVin" and I am not completely sure why I am still trying to get this whole state thing on lock. Any help would be appreciated <3
Below is the full code but I wanted to highlight the import parts above
import React, {useEffect, Component} from 'react';
import {View, Text} from 'react-native';
import firebase from '#react-native-firebase/app';
import auth from '#react-native-firebase/auth';
import firestore from '#react-native-firebase/firestore';
import {Section, Container, InputX, ButtonX} from '../../Components';
class HomePageContent extends Component {
state = {
uData: [],
};
componentDidMount() {
firebase.auth().onAuthStateChanged(user => {
if (user) {
var userID = firebase.auth().currentUser.uid;
const db = firebase.firestore();
let userDB = db.collection('Users').doc(userID);
userDB
.get()
.then(doc => {
if (!doc.exists) {
console.log('No such document!');
} else {
let allUsers = [];
let data = doc.data();
let currentUser = data.fName;
let currentTokens = data.tokens;
allUsers.push({
currentUser,
});
this.setState({uData: allUsers});
}
})
.catch(err => {
console.log('Error getting document', err);
});
} else {
// No user is signed in.
}
});
}
render() {
return (
<View key="usdd" style={{alignItems: 'center'}}>
{this.state.uData.map((value, index) => (
<Section key="ussdf">
<Container key="udf">
<Text key="usddfsdf" style={{fontSize: 25}}>
Welcome {value.currentUser}!
</Text>
<Text key="usddfsdf" style={{fontSize: 25, textAlign: 'center'}}>
Begin Searching Below
{'\n'}
{'\n'}
</Text>
<InputX
label="Vin Number"
style={{backgroundColor: '#fafafa'}}
autoCapitalize="none"
returnKeyType={'next'}
key="uemail"
onChangeText={text => this.setState({currentTypedVin: text})}
/>
<ButtonX
dark={true}
color={'#3990FF'}
label={'Request Report'}
onPress={GetReport}
key="savebut"
/>
</Container>
</Section>
))}
</View>
);
}
}
function GetReport() {
let data = null;
let vinNumb = this.state.currentTypedVin;
let xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener('readystatechange', function() {
if (this.readyState === this.DONE) {
const db = firebase.firestore();
let user = firebase.auth().currentUser.uid;
let cityRef = db.collection('Users').doc(user);
let setWithOptions = cityRef.update({
Reports: firebase.firestore.FieldValue.arrayUnion(
JSON.stringify({
VinReport: this.responseText,
}),
),
//....
});
}
});
xhr.open(
'GET',
'https://vindecoder.p.rapidapi.com/decode_vin?vin=' + vinNumb,
);
xhr.setRequestHeader('x-rapidapi-host', 'vindecoder.p.rapidapi.com');
xhr.setRequestHeader('x-rapidapi-key', 'REMOVED');
xhr.send(data);
}
export default HomePageContent;
Because your GetReport function is out of the React class scope. You may take the function into the class
E.g.
class HomePageContent extends Component {
...your implementation
GetReport = () => {
let data = null;
let vinNumb = this.state.currentTypedVin;
...your implementation
}
render() {
return (
...your implementation...
<ButtonX
dark={true}
color={'#3990FF'}
label={'Request Report'}
onPress={this.GetReport}
key="savebut"
/>
...your implementation...
);
}
}
export default HomePageContent;

Invariant Violation in React Native: Text strings must be rendered within a <Text> component

I'm working on a React-Native project with REST APis, and I've currently got an invariant violation error. I've experienced this before, but I can't quite figure out what is causing it and how to fix it. If someone could point me in the right direction, I would really appreciate it! The full error is pictured below, and appears to be referencing a number of tags in the code, so I'm unsure exactly where it is originating. Thank you for reading, and thanks in advance!
The code is here:
import React, { Component } from 'react'
import { View, Text, Image, StyleSheet, FlatList} from 'react-native';
import * as Font from 'expo-font';
import styled from 'styled-components';
import dimensions from '../components/ScreenSize';
import colours from '../components/Colours';
import { Audio } from 'expo-av';
import { TouchableHighlight } from 'react-native-gesture-handler';
const client_id = {Client_ID}
const client_secret = {Client_Secret}
const item = ({item}) => (
<View style={{ flex:1, flexDirection: 'column', margin:1}}>
<TouchableHighlight onPress={() => this.fetchTracks(item.id)}>
<View>
<Text>{item.name}</Text>/>
</View>
</TouchableHighlight>
</View>
)
export default class HomeScreen extends React.Component {
state={
fontsLoaded:false,
}
async componentDidMount() {
await Font.loadAsync({
'montserrat-regular': require('../assets/fonts/Montserrat/Montserrat-Regular.ttf'),
'montserrat-light': require('../assets/fonts/Montserrat/Montserrat-Light.ttf'),
'montserrat-semibold': require('../assets/fonts/Montserrat/Montserrat-SemiBold.ttf'),
'montserrat-bold': require('../assets/fonts/Montserrat/Montserrat-Bold.ttf'),
}
).then(() => this.setState({ fontsLoaded:true }))
this.getToken();
this.setAudio();
}
constructor (props) {
super(props)
this.playbackInstance=null;
this.state = {
playing:false,
token: '',
DATA:[],
};
}
setAudio=() => {
Audio.setAudioModeAsync({
allowsRecordingIOS:false,
interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_DO_NOT_MIX,
playsInSilentModeIOS: true,
shouldDuckAndroid: true,
interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DO_NOT_MIX,
playThroughEarpieceAndroid: false,
});
}
componentDidCatch(error, info)
{
console.log(error, info.componentStack);
}
getToken = async() =>
{
try
{
const getspotifytoken = await fetch("https://accounts.spotify.com/api/token",
{
method:'POST',
body: `grant_type=client_credentials&client_id=${client_id}&client_secret=${client_secret}`,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const spotifytoken = await getspotifytoken.json();
this.setState({
token: spotifytoken.access_token
});
console.log(this.state.token);
}
catch(err)
{
console.log("Error fetching data", err);
}
}
search = async () => {
try
{
console.log("Searching: mood")
const spotifyApiCall = await fetch(`https://api.spotify.com/v1/browse/categories/mood/playlists?`, {
headers: {
Accept: 'application/json',
Authorization: `Bearer ${this.state.token}`,
"Content-Type":'application/json'
}
})
const spotify = await spotifyApiCall.json();
console.log("Items", spotify);
this.setState({
DATA: spotify.playlists.items,
})
}
catch (err)
{
console.log("Error fetching data", err);
}
}
fetchTracks = async (playlistId) => {
console.log('Playlist ', playlistId)
try
{
const getplaylist = await fetch(`https://api.spotify.com/v1.playlist/${playlistId}`,
{
method:'GET',
headers: {
Accept:"application/json",
Authorization:`Bearer ${this.state.token}`,
"Content-Type":"application/json"
}
});
const playlist = await getplaylist.json();
console.log('music ', playlist.tracks.items[0].preview_url);
}
catch (err)
{
console.log("Error fetching data ", err);
}
}
async _loadNewPlaybackInstance(playing, track) {
if(this.playbackInstance != null)
{
await this.playbackInstance.unloadAsync();
this.playbackInstance.setOnPlaybackStatusUpdate(null);
this.playbackInstance = null;
}
const source = {uri: track};
const initialStatus = {
shouldPlay: true,
rate: 1.0,
shouldCorrectPitch: true,
volume: 1.0,
isMuted: false
};
const {sound, status} = await Audio.Sound.createAsync(
source.initialStatus);
this.playbackInstance=sound;
this.playbackInstance.setIsLoopingAsync(false);
this.playbackInstance.playAsync();
if (this.state.selected === playlistId) {
console.log("Playing, so stop");
this.setState({selected:null});
this.playbackInstance.pauseAsync();
return;
}
this.setState({ selected:playlistId});
this._loadNewPlaybackInstance(true, playlist.tracks.items[0].preview_url);
}
render() {
if(!this.state.fontsLoaded ) {
return null
}
return (
<Container>
<Titlebar>
<Title>Music</Title>
</Titlebar>
<HeaderBar2>
<TouchableHighlight onPress={() => this.search()}>
<Header2>Playlists for your Mood</Header2>
</TouchableHighlight>
</HeaderBar2>
<View style={styles.MainContainer}>
{
this.state.DATA.length == 0 &&
<Text style={{padding:10, color:'#D3D3D3'}}/>
}
<FlatList
data = {this.state.DATA}
renderItem={item}
keyExtractor = {item.id}
numColumns={2}
extraData = {this.state}
/>
</View>
</Container>
);
}
}
I think u just have a little typo ..
check this line: <Text>{item.name}</Text>/>
change the last Text to </Text>

Lodash debounce not working all of a sudden?

I'm using a component I wrote for one app, in a newer app. The code is like 99% identical between the first app, which is working, and the second app. Everything is fine except that debounce is not activating in the new app. What am I doing wrong?
// #flow
import type { Location } from "../redux/reducers/locationReducer";
import * as React from "react";
import { Text, TextInput, View, TouchableOpacity } from "react-native";
import { Input } from "react-native-elements";
import { GoogleMapsApiKey } from "../../.secrets";
import _, { debounce } from "lodash";
import { connect } from "react-redux";
import { setCurrentRegion } from "../redux/actions/locationActions";
export class AutoFillMapSearch extends React.Component<Props, State> {
textInput: ?TextInput;
state: State = {
address: "",
addressPredictions: [],
showPredictions: false
};
async handleAddressChange() {
console.log("handleAddressChange");
const url = `https://maps.googleapis.com/maps/api/place/autocomplete/json?key=${GoogleMapsApiKey}&input=${this.state.address}`;
try {
const result = await fetch(url);
const json = await result.json();
if (json.error_message) throw Error(json.error_message);
this.setState({
addressPredictions: json.predictions,
showPredictions: true
});
// debugger;
} catch (err) {
console.warn(err);
}
}
onChangeText = async (address: string) => {
await this.setState({ address });
console.log("onChangeText");
debounce(this.handleAddressChange.bind(this), 800); // console.log(debounce) confirms that the function is importing correctly.
};
render() {
const predictions = this.state.addressPredictions.map(prediction => (
<TouchableOpacity
style={styles.prediction}
key={prediction.id}
onPress={() => {
this.props.beforeOnPress();
this.onPredictionSelect(prediction);
}}
>
<Text style={text.prediction}>{prediction.description}</Text>
</TouchableOpacity>
));
return (
<View>
<TextInput
ref={ref => (this.textInput = ref)}
onChangeText={this.onChangeText}
value={this.state.address}
style={[styles.input, this.props.style]}
placeholder={"Search"}
autoCorrect={false}
clearButtonMode={"while-editing"}
onBlur={() => {
this.setState({ showPredictions: false });
}}
/>
{this.state.showPredictions && (
<View style={styles.predictionsContainer}>{predictions}</View>
)}
</View>
);
}
}
export default connect(
null,
{ setCurrentRegion }
)(AutoFillMapSearch);
I noticed that the difference in the code was that the older app called handleAddressChange as a second argument to setState. Flow was complaining about this in the new app so I thought async/awaiting setState would work the same way.
So changing it to this works fine (with no flow complaints for some reason. maybe because I've since installed flow-typed lodash. God I love flow-typed!):
onChangeText = async (address: string) => {
this.setState(
{ address },
_.debounce(this.handleAddressChange.bind(this), 800)
);
};

Passing value of component to another Scene to use in post method - react native

I need Some Help as possible.
In my code I have scene that return into my view, an array with names. However, I want to do something also. When I click the name, I want to take the email of the name I have clicked and past to my post method, to return in another scene with information of the email person. Here is my code:
My Users Class with all elements
import React from 'react';
import ListaItens from './ListaUsers'
import BarraNavegacao from './BarraNavegacao';
import {View,Image,Alert,TouchableHighlight,AsyncStorage} from 'react-native';
import axios from 'axios';
export default class Users extends React.Component {
constructor(props) {
super(props);
this.state = {tituloBarraNav: 'Colaboradores',testLocal:''};
}
My refresh function is into Component Users
async refresh() {
let tmp_localData = {};
AsyncStorage.getItem('localData', (err, result) => {
//console.log(result);
tmp_localData = JSON.parse(result);
//console.log('Local temp: ', tmp_localData.User.email);
}).then((result) => {
tmp_localData = JSON.parse(result);
//console.log('Email: ', tmp_localData.email);
axios({
method: 'post',
url: 'my url'
data: {
email: 'someEmail#test.com,
}
},
console.log('aqui esta o email'),
).then((response) => {
//console.log('Get tmpLocal ----------',tmp_localData);
//console.log('Get response ----------',response);
tmp_localData.User = {
"userID": response.data.response.userID,
"displayName": response.data.response.displayName,
"email": response.data.response.email,
"avatar": response.data.response.avatar,
"gender": response.data.response.gender,
"Session": {
"token": response.data.response.token,
},
"FootID": response.data.response.FootID,
};
//this.refresh();
//console.log('Set tmpLocal',tmp_localData);
AsyncStorage.setItem('localData', JSON.stringify(tmp_localData), () => {
}).then((result) => {
this.props.navigator.push({id: 'MenuPrincipal'});
console.log('Navigator',this.props.navigator);
//Alert.alert('Clicou Aqui ');
});
}).catch((error) => {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
Alert.alert('Não foi possivel mudar o utilizador');
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console.log('erro de ligaçao', error.message);
Alert.alert('Não foi possivel mudar o utilizador');
console.log(error.request);
} else {
// Something happened in setting up the request that triggered an Error
console.log('erro de codigo no then', error.message);
Alert.alert('Não foi possivel mudar o utilizador');
}
console.log(error.config);
Alert.alert('Não foi possivel mudar o utilizador');
});
});
}
My render in Users
render(){
const {principal, conteudo,imgConteudo1,imgConteudo2, texto,box}= myStyle;
return(
<View style={principal}>
<BarraNavegacao back navigator={this.props.navigator} tituloProp={this.state.tituloBarraNav}/>
<TouchableHighlight onPress={() => {this.refresh();}}
clearButtonMode={'while-editing'}
activeOpacity={1} underlayColor={'white'}>
<ListaItens/>
</TouchableHighlight>
</View>
);
}
}
I have ListaItems Component that will walk through an array and will put inside ScroolView with map method. So the code is:
My ListaItems Class
import React from 'react';
import { ScrollView} from 'react-native';
import axios from 'axios';
import Items from './Items';
export default class ListaItens extends React.Component {
constructor(props) {
super(props);
this.state = {listaItens: [], listaEmail: [] };
}
componentWillMount() {
//request http
axios.get('my url')
.then((response) => {
this.setState({listaItens: response.data.response})
})
.catch(() => {
console.log('Erro ao imprimir os dados')
});
}
render() {
return (
<ScrollView>
{this.state.listaItens.map(item =>(<Items key={item.email} item={item}/>))}
</ScrollView>
);
}
}
The last component is the component the build what i want to show inside scrollview in ListaItems. The component name is Items. the code is:
My Items Class
import React, {Component} from 'react';
import {Text, Alert, View, Image,} from 'react-native';
export default class Items extends Component {
constructor(props) {
super(props);
this.state = {listaEmail: ''};
}
render() {
const {foto, conteudo, texto, box, test} = estilo;
return (
<View>
<Text/>
<Text/>
<View style={conteudo}>
<Image style={foto} source={{uri: this.props.item.avatar}}/>
<Text style={texto}>{this.props.item.displayName}</Text>
</View>
<View style={test}>
<Text style={texto}>{this.props.item.email}</Text>
</View>
</View>
);
}
}
So, in Users Class for refresh() function in the post method on this email: "someEmail#test.com", I want to be dynamic, when I click the name of a person in Items Class, I want to take the the email here on this.props.item.email and put in parameter on post method of Users Class----refresh()----axios()---Data---email:the email i want to past.
A litle help here, please. I am desperate right now because i have tryied and I did not make it
First move the Touchable to the item
export default class Items extends Component {
render() {
const { foto, conteudo, texto, box, test } = estilo;
return (
<View> //I'm not sure if the this.props.item.email is the one you use, just change it if you need.
<TouchableHighlight onPress={() => { this.props.callback(this.props.item.email); }}
clearButtonMode={'while-editing'}
activeOpacity={1} underlayColor={'white'}>
<Text />
<Text />
<View style={conteudo}>
<Image style={foto} source={{ uri: this.props.item.avatar }} />
<Text style={texto}>{this.props.item.displayName}</Text>
<View style={test}>
<Text>{this.props.item.email}</Text>
</View>
</View>
</TouchableHighlight>
</View>
);
}
}
Them change you function to receive the email param.
refresh = (email) => {
let tmp_localData = {};
AsyncStorage.getItem('localData', (err, result) => {
tmp_localData = result;
}).then((result) => {
axios({
method: 'post',
url: 'my Url',
data: {
email: email,
}
})
})
}
And them you can pass the function to component via props
render() {
const { principal, conteudo, imgConteudo1, imgConteudo2, texto, box } =
myStyle;
return (
<View style={principal} >
<BarraNavegacao back navigator={this.props.navigator} tituloProp={this.state.tituloBarraNav} />
<ListaItens callback={this.refresh} />
</View>
);
}