In the screen that I'm trying to put up. I get the ID of a product. The previous screen being a list of products, which come from an API. I get this id thanks to props.data
The console.log ('props', this.props.data) works fine and returns the correct ID to me regardless of the product clicked.
With the ID of this product, I want to find the detailed information of this product (the reference, the family, the price, the stock etc.).
I created this function to call the product detail via my API.
initListData = async () => {
if (parseInt(this.state.productId) > 0) {
let product_data = await getProduct(this.state.productId);
console.log('product_data', product_data)
this.setState({
displayArray: product_data,
loadMoreVisible: (product_data.length >= 15 ? true : false),
currentPage: 2
});
}
};
I think the problem is that the displayArray[] is empty so
let product_data = await getProduct(this.state.productId);
Doesn't work.
And I get this error: Cannot update a component from inside the function body of a different component
Can you explain to me what's wrong ?
Full code
export default class Information extends Component {
constructor(props) {
super(props);
this.state = {
productId: this.props.data,
displayArray: [],
}
console.log('props', this.props.data) // ok, ça fonctionne, on récupère bien l'ID du produit cliqué
};
initListData = async () => {
if (parseInt(this.state.productId) > 0) {
let product_data = await getProduct(this.state.productId);
console.log('product_data', product_data)
this.setState({
displayArray: product_data,
loadMoreVisible: (product_data.length >= 15 ? true : false),
currentPage: 2
});
}
};
async UNSAFE_componentWillMount() {
this.initListData();
}
render() {
console.log('ça c\'est data = ', this.props.data );
console.log('ça c\'est les props =', this.props );
console.log('ça c\'est le state = ', this.state );
return (
<ScrollView contentContainerStyle={{flex: 1}}>
{
this.state.displayArray.map((item, i) => (
<ListItem bottomDivider>
<Icon name='flight-takeoff' />
<ListItem.Content>
<ListItem.Title style={{color: '#d35400'}}>{item.name}</ListItem.Title>
<ListItem.Subtitle style={{ color: '#F78400' }}>
{i18n.t("information.family")}: {item.family_id}
</ListItem.Subtitle>
<ListItem.Subtitle style={{ color: '#F78400' }}>
{i18n.t("information.reference")}: {item.reference}
</ListItem.Subtitle>
<ListItem.Subtitle style={{ color: '#F78400' }}>
{i18n.t("information.id")}: {item.id}
</ListItem.Subtitle>
<ListItem.Subtitle style={{ color: '#F78400' }}>
{i18n.t("information.cost")}: {item.cost}
</ListItem.Subtitle>
<ListItem.Subtitle style={{ color: '#F78400' }}>
{i18n.t("information.description")}: {item.description}
</ListItem.Subtitle>
<ListItem.Subtitle style={{ color: '#F78400' }}>
{i18n.t("information.stock")}: {item.stock_status}
</ListItem.Subtitle>
</ListItem.Content>
</ListItem>
))
}
</ScrollView>
);
}
}
getProduct function : [I just have to hide the real url]
export async function getProduct(product_id) {
const abortController = new AbortController();
let user_id = await retrieveProfileUserId();
let lang = await retrieveAppLang();
let access_token = await renewAccessToken();
let result = {};
if (parseInt(product_id) > 0 && access_token != '' && parseInt(user_id) > 0) {
try {
let response = await fetch(
API_URL +
"/products/" + product_id +
"?user_id=" + user_id +
"&society_id=" + API_SOCIETYID +
"&access_token=" + access_token +
"&lang=" + lang,
{
method: "GET",
signal: abortController.signal,
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Bearer " + API_SECRETKEY,
"Cache-Control": "no-cache, no-store, must-revalidate",
Pragma: "no-cache",
Expires: "0"
}
}
)
.then(response => response.json())
.then(responseData => {
if (responseData.status == 200 && responseData.data) {
console.log("getProduct()::success", responseData.data);
result = responseData.data;
} else if (
responseData.status >= 200 && responseData.status <= 404 &&
responseData.data.error && responseData.data.error.length >= 3
) {
// Handle error
throw responseData.data.error;
} else {
throw "error";
}
});
} catch (error) {
//console.log(error);
abortController.abort();
}
}
Try changing a few things around and it should work.
I also don't like setting state directly inside the fn, so I propose the following change:
initListData = async () => {
if (this.props.data != null) {
const productData = await getProduct(this.state.productId);
return productData; // You are missing this, this is vital!
}
};
async componentDidMount() {
const data = await this.initListData(); // don't forget await here if you're using async
if (data.id) {
this.setState((prevState) => ({
displayArray: [...prevState.displayArray, data],
loadMoreVisible: ..., // I don't know what do you want here, because again, you receive an object from your backend, not an array.
currentPage: 2
}));
}
}
Related
I'm using expo in managed flow. Also, I'm using expo-task-Manager and expo-location. I'm using the expo documentation but I don't know why when I'm in the background it appears an error saying: [Unhandled promise rejection: Error: Not authorized to use background location services.]
node_modules/react-native/Libraries/BatchedBridge/NativeModules.js:103:50 in promiseMethodWrapper
node_modules/#unimodules/react-native-adapter/build/NativeModulesProxy.native.js:15:23 in moduleName.methodInfo.name
node_modules/expo-location/build/Location.js: in startLocationUpdatesAsync
node_modules/regenerator-runtime/runtime.js:63:36 in tryCatch
node_modules/regenerator-runtime/runtime.js:293:29 in invoke
node_modules/regenerator-runtime/runtime.js:63:36 in tryCatch
node_modules/regenerator-runtime/runtime.js:154:27 in invoke
My code is the following:
import React from 'react';
import {connect} from 'react-redux';
import {View, TouchableHighlight, Text, StyleSheet} from 'react-native';
import { activateSearch, actualLocation, arriveToken, logging, localFound, arriveShop } from '../redux/actions';
import { Alert, Platform } from 'react-native'
import * as Permissions from 'expo-permissions';
import * as Linking from 'expo-linking';
import * as Notifications from 'expo-notifications';
import * as Location from 'expo-location';
import * as TaskManager from 'expo-task-manager';
import axios from 'axios';
import {baseURL} from '../consts/url';
const LOCATION_TASK_NAME = 'backgroud-location-tasks'
const hasNotificationPermission = async () => {
try {
const { status: existingStatus } = await Permissions.getAsync(Permissions.NOTIFICATIONS);
let finalStatus = existingStatus;
if (finalStatus === 'granted') return true;
if (finalStatus !== 'granted') {
Alert.alert(
'Warning',
'You will not receive notifications if you do not enable push notifications. If you would like to receive notifications, please enable push notifications for Fin in your settings.',
[
{ text: 'Cancel'},
// we can automatically open our app in their settings
// so there's less friction in turning notifications on
{ text: 'Enable Notifications', onPress: () => Platform.OS === 'ios' ? Linking.openURL('app-settings:') : Linking.openSettings() }
]
)
return false;
}
} catch (error) {
Alert.alert(
'Error',
'Something went wrong while check your notification permissions, please try again later.'
);
return false;
}
}
const hasGeolocationPermission = async () => {
try {
const { status } = await Location.requestPermissionsAsync();
let finalStatus = status
if (finalStatus === 'granted') return true;
if (finalStatus !== 'granted') {
Alert.alert(
'Warning',
'You will not search if you do not enable geolocation in this app. If you would like to search, please enable geolocation for Fin in your settings.',
[
{ text: 'Cancel'},
// we can automatically open our app in their settings
// so there's less friction in turning geolocation on
{ text: 'Enable Geolocation', onPress: () => Platform.OS === 'ios' ? Linking.openURL('app-settings:') : Linking.openSettings() }
]
)
return false;
}
} catch (error) {
Alert.alert(
'Error',
'Something went wrong while check your geolocation permissions, please try again later.'
);
return false;
}
}
const checkIfLocationEnabled = async () => {
let enabled = await Location.hasServicesEnabledAsync();
if (!enabled){
alert('Location service not enabled, please enable it to continue')
}
else {
return enabled;
}
}
class IndexScreen extends React.Component {
async componentDidMount() {
hasNotificationPermission()
hasGeolocationPermission()
this.registerForPushNotificationsAsync()
Notifications.addNotificationReceivedListener(notification => {
Alert.alert(notification.request.content.title, notification.request.content.body)
console.log(notification)
this.props.navigation('App');
})
Notifications.addNotificationResponseReceivedListener( response => {
console.log(response);
this.props.navigation('App');
}) /*cuando el usuario pulsa encima, cambia de pantalla*/
this.myInterval = setInterval(async () => {
if (this.props.activated){
let Notpermission = await hasNotificationPermission();
let Geopermission = await hasGeolocationPermission();
let EnableLocation = await checkIfLocationEnabled();
if (Notpermission && Geopermission && EnableLocation){
this.getPosition();
this.sendLocation();
console.log("Se ha activado")
} //Si cambia algo de los permisos, se deja de enviar.
else {return}
}
}, 30000)
}
async componentWillUnmount(){
clearInterval(this.myInterval)
}
activate = async () => {
let Notpermission = await hasNotificationPermission();
let Geopermission = await hasGeolocationPermission();
let EnableLocation = await checkIfLocationEnabled();
if (Notpermission && Geopermission && EnableLocation){
if (!this.props.activated){
this.props.dispatch(activateSearch());
this.getPosition();
this.sendLocation();
const { status } = await Location.requestPermissionsAsync();
if (status === 'granted') {
TaskManager.defineTask(LOCATION_TASK_NAME, async ({ data: {locations}, error }) => {
if (error) {
// Error occurred - check `error.message` for more details.
return;
}
const [location] = locations;
console.log(location);
try{
await axios.post(baseURL+'/location', {location})
}catch (err) {
console.log(err)
}
});
await Location.startLocationUpdatesAsync(LOCATION_TASK_NAME, {
accuracy: Location.Accuracy.Balanced,
timeInterval: 10000,
foregroundService: {
notificationTitle: "BackgroundLocation Is On",
notificationBody: 'To turn off, go back to the app and switch something off.',
}});
}
}
else
this.props.dispatch(activateSearch())
if (this.props.locationdetected)
this.props.dispatch(localFound());
//this.deleteToken()
}
else{
return
}
}
render() {
if (this.props.logged){
return(
<View style={{ flex:1, flexDirection: 'column', alignItems:'center', justifyContent:'space-around'}}>
<Text style={{flex:1, fontSize: 35 }}> Welcome {this.props.username} to this demo App </Text>
<Text style={{flex:1, fontSize: 35 }}> Press 'Start Search'</Text>
<Text style={{flex:1, fontSize: 20 }}> Your expo push token: {this.props.token}</Text>
<Text style={{flex:1, fontSize: 20 }}> Geolocation & Push notifications: {this.props.activated? "true" : "false"} </Text>
<TouchableHighlight style={styles.button} onPress = {() => this.activate()}>
<Text> {this.props.activated ? "Stop Search" : "Start Search"}</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.button} onPress = {() => this.logout()}>
<Text>Logout</Text>
</TouchableHighlight>
</View>
)
}
else{
return(
<View style={{ flex:1, flexDirection: 'column', alignItems:'center', justifyContent:'space-around'}}>
<Text style={{flex:1, fontSize: 35 }}> You need to be logged </Text>
</View>
)
}
}
async registerForPushNotificationsAsync() {
try{
let token = (await Notifications.getExpoPushTokenAsync()).data;
this.props.dispatch(arriveToken(token))
this.sendToken(token);
if (Platform.OS === 'android') {
Notifications.setNotificationChannelAsync('default', { /*en Android es necesario poner un canal por defecto*/
name: 'default',
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
});
}
return token;
}
catch(error){
console.log("No se ha podido obtener el token para push notifications")
}
}
async getPosition() {
try{
const { coords } = await Location.getCurrentPositionAsync({});
let position = coords;
this.props.dispatch(actualLocation(position.latitude, position.longitude))
console.log(this.props.latitud)
}
catch (error) {
console.log("getPosition -> error", error);
}
}
async sendToken(token){
let response = await fetch(baseURL+'/pushtoken', {
method: 'POST',
headers: {
Accept: 'application/json',
'Accept-encoding': 'gzip, deflate',
'Content-Type': 'application/json',
},
//credentials: 'include',
body: JSON.stringify({pushtoken: token}),
});
if (response.status == 401){
alert('La sesión ha finalizado por exceso de espera. Vuelva a hacer Log in.')
this.props.dispatch(logging(''));
}else if (response.status != 200){
alert('Ha surgido un error al guardar el pushtoken.')
console.log(response.status)
}
}
async logout(){
let response = await fetch(baseURL+'/logout', {
method: 'POST',
headers: {
Accept: 'application/json',
'Accept-encoding': 'gzip, deflate',
'Content-Type': 'application/json',
},
//credentials: 'include',
});
if (this.props.activated == true){this.props.dispatch(activateSearch())}
if (this.props.locationdetected == true){this.props.dispatch(localFound())}
this.props.dispatch(logging(""))
}
async sendLocation(){
let response = await fetch(baseURL+'/location', {
method: 'POST',
headers: {
Accept: 'application/json',
'Accept-encoding': 'gzip, deflate',
'Content-Type': 'application/json',
},
//credentials: 'include',
body: JSON.stringify({latitud: this.props.latitud, longitud: this.props.longitud, shopfind: this.props.locationdetected}),
});
let responsed = await response.json();
if (response.status == 401){
alert('La sesión ha finalizado por exceso de espera. Vuelva a hacer Log in.')
if(this.props.activated && this.props.logged){
if(this.props.locationdetected){
this.props.dispatch(localFound())
}
this.props.dispatch(activateSearch());
this.props.dispatch(logging(''));
}
}
else if (responsed.shop && !this.props.locationdetected) {
this.props.dispatch(localFound())
let placementsreformed = responsed.shop.placements.map(item => {
return {...item,
quantity: 0}
})
responsed.shop.placements = placementsreformed;
this.props.dispatch(arriveShop(responsed.shop))
console.log("tienda enviada")
}
else {
if (this.props.locationdetected && !responsed.shop){
this.props.dispatch(localFound())
console.log("Se ha dejado de encontrar tiendas")
}
else{
return;
}
}
}
}
const styles = StyleSheet.create({
button: {
height: 60,
width: 100,
flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: 'red',
fontSize: 25,
textAlign: 'center',
padding: 10
}
}
);
function mapStateToProps(state) {
return {
...state
};
}
//export default App;
export default connect(mapStateToProps)(IndexScreen);
I need some help please.
in one of my pages I call a component. However, it is not displayed. I'm not sure what's wrong, and how to find out where exactly the error came from. I know that the code contained in the component is good since I am calling it in another screen. I wonder if it's not because of 'parent' use
<View style={{width: "66.66%"}}>
<MapView parent={this} />
<Text>{"ICIII"}</Text>
</View>
There is just the text that is displayed (the text was here just to test). I hope someone can help me try to understand where the problem come from, I know I have a lot to learn so thank you for your time and explanations.
This is the component MapView :
export default class MapView extends Component {
constructor(props) {
super(props);
this.state = {
progress: new Animated.Value(0),
onLoading: true,
height: 0,
user_id: 0,
lang: "en",
access_token: "",
stats : "",
screen_updated: 0,
map_request_periods: "",
map_request_periods_title: "",
map_request_periods_val: "*"
};
}
performMessageFromWebView(e) {
if (e.nativeEvent && e.nativeEvent.data) {
let id = e.nativeEvent.data.replace('flightId=', '');
if (parseInt(id) > 0) {
this.props.navigation.navigate("UpdateTripsForm", {flightId: parseInt(id)}); // Open Screen UpdateTripForm.js
return true;
}
}
return false;
}
initUserData = async () => {
let user_id = await retrieveProfileUserId();
let lang = await retrieveAppLang();
let user_stats = await getUserFlightStats();
let access_token = await renewAccessToken();
if (user_id && lang && access_token && parseInt(user_id) > 0) {
this.setState({
user_id: parseInt(user_id),
lang: lang,
stats: user_stats,
access_token: access_token,
});
}
};
async UNSAFE_componentWillMount() {
this.initUserData();
}
async componentDidMount() {
// Refresh data
this.props.navigation.addListener("didFocus", async (payload) => {
let user_id = await retrieveProfileUserId();
let user_stats = await getUserFlightStats();
let access_token = await renewAccessToken();
if (user_id && access_token && parseInt(user_id) > 0) {
this.setState({
screen_updated: this.state.screen_updated + 1,
user_id: parseInt(user_id),
stats: user_stats,
access_token: access_token,
map_request_periods: "", // Force reinitialize choice
map_request_periods_title: "",
map_request_periods_val: "*"
});
console.log(Device.DeviceType);
}
// Force PORTRAIT orientation
await ScreenOrientation.getOrientationAsync().then(
(data_orientation) => {
if (parseInt(data_orientation) == parseInt(ScreenOrientation.Orientation.LANDSCAPE_LEFT) || parseInt(data_orientation) == parseInt(ScreenOrientation.Orientation.LANDSCAPE_RIGHT)) {
ScreenOrientation.lockAsync(
ScreenOrientation.OrientationLock.PORTRAIT_UP
);
}
}
);
});
// const data = this.props.navigation.getParam('this.selectedStartDate', 'this.selectedEndDate');
// this.setState({ this.state.selectedStartDate, this.state.selectedEndDate});
Animated.timing(this.state.progress, {
toValue: 1,
duration: 3000,
easing: Easing.linear,
useNativeDriver: true,
}).start();
if (this.state.onLoading == true) {
setTimeout(
function () {
this.setState({ onLoading: false });
}.bind(this),
3000
);
}
}
render() {
return (
<View>
<WebView
geolocationEnabled={true}
javaScriptEnabled={true}
scrollEnabled={false}
overScrollMode="never"
source={{
uri:
"https://www.blzlva.org/fr/mestrips" +
"?society_id=" + API_SOCIETYID +
"&user_id=" + this.state.user_id +
"&lang=" + this.state.lang +
"&hidezoom=1" +
"&access_token=" + this.state.access_token +
"&screen=" + this.state.screen_updated
}}
originWhitelist={[
"https://www.blzblz.org",
"https://www.blabla.com"
]}
scalesPageToFit={true}
onMessage={(m) => this.performMessageFromWebView(m)}
style={{ marginHorizontal: 0, backgroundColor: "transparent" }}
/>
</View>
);
}
}
Import the map component which page you want to use it like following,
import Map from '../../map.js'
then use the component inside a view like following,
<View style={{width:100px}}>
<Map/>
</View>
I am not able to get an alert when the api response fails.I am trying to add the alert in where the actions are getting dispatched.Can we trigger an alert of we have redirect to a different page after the submission? Is there any other way to show the error msg when the api response fails.
const saveOPPInfo = () => {
this.setState({
_firstNameEmpty: isEmpty(_firstName),
_lastNameEmpty: isEmpty(_lastName),
_emailNotValid: !validateEmail(_email)
});
if (
this.isSaveAttempted ||
isEmpty(_firstName) ||
isEmpty(_lastName) ||
!validateEmail(_email)
) {
return;
}
this.isSaveAttempted = true;
this.setState({ _isFetching: true });
if (action === "ADD") {
const jsonPayload = [
{
email: _email,
firstName: _firstName,
lastName: _lastName,
isPrimary: false
}
];
addOtherPickupPerson({ purchaseContractId, jsonPayload }).then(() => {
GroceryNotifierApi.events().emitOnAction("saveOPPInfo", "");
});
} else {
const jsonPayload = {
email: _email,
firstName: _firstName,
lastName: _lastName,
isPrimary: false
};
editOtherPickupPerson({ purchaseContractId, jsonPayload, pickupPersonId: _id }).then(() => {
GroceryNotifierApi.events().emitOnAction("saveOPPInfo", "");
});
}
};
here is the part of jsx
<View
style={{
paddingLeft: 20,
paddingRight: 20,
paddingTop: 24
}}
>
{action === "ADD" ? (
<Body>
{OPP_ADD_OPP_DESC}
<Body
onPress={() => nativeNav.navigateToOPPLearnMore()}
style={{ textDecorationLine: "underline" }}
>
{OPP_LEARN_MORE}
</Body>
</Body>
) : (
<View />
)}
</View>
{_isFetching && (
<View style={{ height: 120 }}>
<CircularIndicator />
</View>
)}
<View style={styles.bottom}>
<PrimaryButton
style={styles.saveButton}
testID="save"
block
onPress={saveOPPInfo}
disabled={this.isSaveAttempted || _firstNameEmpty || _lastNameEmpty || _emailNotValid}
>
{isIOS ? "Save" : "SAVE"}
</PrimaryButton>
{action === "ADD" ? (
<View />
) : (
<LinkButton onPress={removeOPPInfo} disabled={this.isSaveAttempted}>
{OPP_REMOVE}
</LinkButton>
)}
</View>
</View>
);
}
this is how the action looks
export const addOtherPickupPersonRequest = createAction(ADD_OTHER_PICKUP_PERSON_REQUEST);
export const addOtherPickupPersonSuccess = createAction(ADD_OTHER_PICKUP_PERSON_SUCCESS);
export const addOtherPickupPersonFail = createAction(ADD_OTHER_PICKUP_PERSON_FAIL);
export const addOtherPickupPerson = ({ purchaseContractId, jsonPayload }) => {
return async function(dispatch) {
store.dispatch(addOtherPickupPersonRequest());
let response;
let responseJson;
try {
const startTime = new Date().getTime();
response = await fetchAddOtherPickupPerson(purchaseContractId, jsonPayload);
if (response.status >= 200 && response.status < 300) {
trackPerformance("checkout-add-opp-api", startTime, "performance-metric");
responseJson = await response.json();
store.dispatch(addOtherPickupPersonSuccess(responseJson));
return responseJson;
} else {
Alert.alert(
"Oops22!",
"Something is not working here. Please check back later.",
[{ text: "Okay" }],
{ cancelable: false }
);
await Promise.reject(err);
}
} catch (err) {
trackErrorEvent("checkout-add-opp-api", { ...defaultPayload({ err }) }, "api-error");
Alert.alert(
"Oops!",
"Something is not working here. Please check back later.",
[{ text: "Okay" }],
{ cancelable: false }
);
return store.dispatch(addOtherPickupPersonFail(err));
}
};
};
I want to show an alert when the response.status is not response.status >= 200 && response.status < 300)
I had been developing my app for Web, and it has been working properly. However, when I ran the same app within Expo / Android, I got this error. Hard to know what it is about from the description.
This is the full error message:
Cannot add a child that doesn't have a YogaNode to a parent without a measure function! (Trying to add a '[RCTVirtualText 507]' to a '[RCTView 509]')
Do you know what it could possibly be?
This seems to be the js file that is triggering it:
...
export class SubjectListAssignScreen extends React.Component {
state = {
subjectList: [],
subListLoading: true,
};
constructor(props) {
super(props);
};
scrollDimensions = [{
width: Math.round(Dimensions.get('window').width - 20),
maxHeight: Math.round(Dimensions.get('window').height - 200)
}];
...
_getSubjects = async(text) => {
try {
await this.setState({ subListLoading: true });
let lQueryRes = await API.graphql(graphqlOperation(cqueries.listSubjectsCustom, {}));
await console.log('==> Subjects Query');
await console.log(lQueryRes);
await this.setState({ subjectList: lQueryRes.data.listSubjects.items });
await this.setState({ subListLoading: false });
}
catch (e) {
console.log("==> DB Error");
console.log(e);
await this.setState({ subListLoading: false });
};
};
...
_subjectItems = (value) => {
console.log(value.desc);
let lnum = (typeof value["num"] !== 'undefined') ? value["num"].toString() : null;
let desc = value["desc"].toString();
let lastName = (typeof value["users"][0] !== 'undefined') ? value["users"][0]["lastname"].toString() : null;
let ltype = value["type"].toString();
return (
<DataTable.Row onPress={() => {
this.props.navigation.navigate("UserListScreen", {pnum: lnum, ptype: ltype});
}}>
<DataTable.Cell>
{this._getTypeIcon(ltype)}
</DataTable.Cell>
<DataTable.Cell>
<Text>{desc}</Text>
</DataTable.Cell>
<DataTable.Cell>
<Text>{ lastName }</Text>
</DataTable.Cell>
</DataTable.Row>
);
};
async componentDidMount() {
try {
await this._getSubjects();
}
catch (e) {
console.log("==> componentDidMount error");
console.log(e);
};
};
isCloseToBottom = ({ layoutMeasurement, contentOffset, contentSize }) => {
const paddingToBottom = 20;
return layoutMeasurement.height + contentOffset.y >=
contentSize.height - paddingToBottom;
};
fetchMore = () => {
};
render() {
let sDimensions = this.scrollDimensions;
return (
<View style={{flex:20, margin:4, flexDirection:"column", justifyContent:"flex-start"}}>
<Title style={{flex:1}}>Lista de Demandas</Title>
<SafeAreaView style={[{flex:19, }, sDimensions]}>
<ScrollView
contentContainerStyle={{}}
onScroll={({nativeEvent}) => {
if (this.isCloseToBottom(nativeEvent)) {
this.fetchMore();
}}}
>
<DataTable>
<DataTable.Header>
<DataTable.Title>Type</DataTable.Title>
<DataTable.Title>Subj</DataTable.Title>
<DataTable.Title>Resp.</DataTable.Title>
</DataTable.Header>
{ !this.state.subListLoading ?
<FlatList
data={this.state.subjectList}
renderItem={({item})=>this._subjectItems(item)}
keyExtractor={item => item.desc}
/>
:
<ActivityIndicator />
}
</DataTable>
</ScrollView>
</SafeAreaView>
</View>
)
}
}
Using Expo 37, React Native paper and AWS Amplify.
As I had such a hard time trying to find which components were not compatible, I simply dropped my full development environment, create a clean one and pulled the latest commit again, checking all components version by version and making sure all of them were at the -g version. The error has stopped after that.
i am trying to fetch data from some source and storing it in some variable .
But I come with an error that state is not updating.
this.setState({imgLink: data.items[0].snippet.thumbnails.default.url},
() =>
{
console.log(this.state.imgLink);
});
I wanted to print the new value in render method but it shows me nothing.
import React,{Component} from 'react';
import {View,Text,TextInput,ScrollView,Image} from
'react-native';
import { Icon } from 'react-native-elements';
import YTSearch from 'youtube-api-search';
import styles from './StatsStyle';
const API_KEY = '' // hided for stackoverflow ;
var query = '';
export default class StatsScreen extends Component
{
constructor(props)
{
super(props);
this.state = {
term: '',
imgLink: '',
width: 0,
height: 0,
title: '',
totalViews: 0,
totalSubs: 0,
totalVideos: 0 ,
channelId : '' ,
url: '',
}
};
fetchData = data => {
console.log('this is fetchData',data.items[0].statistics.subscriberCount);
this.setState({imgLink: data.items[0].snippet.thumbnails.default.url},
() =>
{
console.log('llllll',this.state.imgLink);
});
console.log('llllll',this.state.imgLink);
this.setState({width: data.items[0].snippet.thumbnails.default.url.width});
this.setState({height: data.items[0].snippet.thumbnails.default.url.height});
this.setState({title: data.items[0].snippet.title});
this.setState({totalSubs: data.items[0].statistics.subscriberCount});
this.setState({totalViews: data.items[0].statistics.viewCount});
this.setState({totalVideos: data.items[0].statistics.videoCount});
}
updateSubscribers = response =>
{
this.setState({totalSubs:
response.items[0].statistics.subscriberCount});
}
onPressedButton = channelId =>
{
var url =
'https://www.googleapis.com/youtube/v3/channels?
key='+API_KEY+'&id=' + channelId +
'&part=snippet,contentDetails,statistics';
this.setState({url: url});
return fetch(url)
.then((response) =>
{
return response.json();
console.log("popo",response);
})
// fetchData(data);
.then((data) => {
this.fetchData(data);
console.log('lol',this.state.imgLink);
console.log('hello',this.state);
})
.catch((error) => {
console.log(error);
})
//now fetching the response from the yt api again
//and again
.setInterval(() =>
{
var url =
'https://www.googleapis.com/youtube/v3/channels?
key='+API_KEY+'o&id=' + channelId +
'&part=statistics';
return fetch(url)
.then((response) =>
{
return response.json()
})
.then((data) => {
this.updateSubscribers(data)
},0)
.catch((error) => {
console.log(error);
});
});
}
render()
{
let{imgLink,totalSubs,totalViews,totalVideos,width,
height,title,channelId,videos,loading,term} =
this.state;
return(
<View style = {styles.container}>
<ScrollView>
<View style = {styles.results}>
<Image style = {
{
width:width,height:height,
alignItems:'center',borderRadius:50
,marginLeft:'auto',marginRight: 'auto',marginTop:
30
}
}
source = {{uri: imgLink}}/>
<Text style = {styles.title}>{title}</Text>
<Text style = {{fontSize: 40,fontWeight:
'bold'}}>Subscribers</Text>
<Text style = {styles.subs}>{totalSubs}</Text>
<Text style = {{fontSize: 40,fontWeight:
'bold'}}>TotalViews</Text>
<Text style = {styles.views}>{totalViews}</Text>
<Text style = {{fontSize: 40,fontWeight:
'bold'}}>TotalVideos</Text>
<Text style = {styles.videos}>{totalVideos}</Text>
</View>
</ScrollView>
</View>
);
}
}