React native app crashes when some components module are being imported - ios

My index.ts file looks like as following:
import StaffMembers from './StaffMembers';
import GuestMembers from './GuestMembers';
export {
StaffMembers,
GuestMembers,
};
My folder structure looks like
This is my StaffMembers.tsx file :
import React from 'react';
import { AppDivider, CustomLabel } from '.';
import { View } from 'react-native-animatable';
import styles from '../styles';
import { Dropdown, TextInput, Label } from '../../../../components';
const StaffMembers: React.FC<{
member: string;
organisation: string;
orgLabel: string;
canDelete: () => void;
errors: any;
onDelete: () => void;
onValueUpdate: (updated: any) => void;
options: any[];
onDropdownStateChange: () => void;
zIndex: number;
onBlur: (fieldName: string) => void;
}> = ({
member,
organisation,
orgLabel,
canDelete,
errors = {},
onDelete = () => {},
onValueUpdate = () => {},
options = [],
zIndex = 1,
onBlur = () => console.log(),
}) => {
return (
<View style={[styles.listItem, { zIndex }]}>
<View style={{ flex: 1 }}>
<Dropdown
label={
canDelete ? (
<CustomLabel
title={<Label title='Staff Member' required />}
onDelete={onDelete}
/>
) : (
'Staff Member'
)
}
data={options}
onSelectItem={item => onValueUpdate({ member: item.value, ...item })}
errorMessage={errors.member}
value={member}
onBlur={() => onBlur('member')}
required
/>
</View>
<View style={{ flex: 1 }}>
<TextInput
disabled={true}
label={'Employee ID'}
value={organisation}
errorMessage={errors.organisation}
onChangeText={(val: string) => onValueUpdate({ organisation: val })}
/>
</View>
<AppDivider />
</View>
);
};
export default StaffMembers;
I'm importing components as
import { StaffMembers, GuestMembers } from '../request/components';
However when my app screen needs to load the component, it crashes giving the below error: Error when app crashes while loading component
When I edit the component's file and save it again, the app works fine.
Is there anything that I'm missing while importing the component? or something else?

The error clearly stat that you are not exporting the component/screen,
You are importing StaffMembers, GuestMembers which are modules, and not a class or component nested in the file, to solve this:
create index.js file in the root directory of ../request/components, and inside index.js file:
import StaffMembers from './StaffMembers';
import GuestMembers from './GuestMembers ';
export {
StaffMembers,
GuestMembers
};
now you can import the modules easily as you need.

Related

React Native NOT rendering data from database on IOS

I have problem with render data on IOS Simulator. Render is work properly on website, but on IOS I still got stuck on "Loading.." text.
Here is my code:
import React from 'react'
import { useState } from 'react';
import { useEffect } from 'react';
import { SafeAreaView, Text, View, StyleSheet, Image, Alert } from 'react-native';
import { Card } from 'react-native-paper'
import firebase from 'firebase'
import Button from '../components/Button'
import Background from '../components/Background'
import TopBar from '../components/TopBar'
export default function HomeScreen({ navigation }) {
const [data, setData] = useState([])
const sampleData = [{id:0, title:"One"}, {id:1, title: "Two"}]
useEffect(() =>
{
const donorsData = [];
firebase.database()
.ref("testdb")
.orderByChild("isDonor")
.equalTo(true)
.once("value")
.then((results) => {
results.forEach((snapshot) => {
donorsData.push(snapshot.val());
});
setData(donorsData);
});
}, [])
const card = data.length > 0
? data.map(item =>
{
return <Card key={item.uid} style={{ marginBottom: 20, borderRadius: 10, }}>
<Text>{item.name}</Text>
<Text>{item.description}</Text>
<Image src={item.photo}></Image>
</Card>
})
: <Text>Loading...</Text>
return (
<View style={styles.container}>
{card}
</View>
);
}
On website is everything ok Website Screen
But on IOS Simulator I got only Loading
IOS Screen
I tried a lot of solutions found here, but no one works with this case. I think is probably because iOS doesn't have data? When I put console log at to top of return, I got nothing.
This might be a race condition error. You shouldn't rely on the data being fetched within 1500ms.
If that doesn't work. Make sure your result from firebase is correct.
Maybe something like this?
const [data, setData] = useState([])
const fetchDonorData = () => {
firebase.database()
.ref("testdb")
.orderByChild("isDonor")
.equalTo(true)
.once("value")
.then((results) => {
console.log({result}) //Make sure the data looks the way you want it
const mappedResult = results?.map(snapshot => snapshot.val())
setData(mappedResult)
})
}
useEffect(() => {
fetchDonorData()
}, [])
const renderItem = ({item}) =>
<Card style={{ marginBottom: 20, borderRadius: 10, }}>
<Text>{item.name}</Text>
<Text>{item.description}</Text>
<Image src={item.photo}></Image>
</Card>
return (
<View style={styles.container}>
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={({item}) => item.uid}
ListEmptyComponent={<Text>Loading...</Text>}
/>
</View>
)

How to reload image url one more time if url shows error in loading

I am trying to load images from URL on flatlist using Image Component. In this component there is a property (onError?: () => void ) this property is called on an image fetching error.
When I run my app in low network some images failed to load, so what code should I write in (onError?: () => void ) so that the URL that failed to load images should load one more time in low network.
I am creating this App in React Native for iOS
I have done this :
App.js
import React, { useState } from 'react';
import Product from './product';
import {
FlatList,
SafeAreaView
} from 'react-native';
const products = [
{productImage: "https://media.istockphoto.com/photos/poverty-concept-used-red-shoes-for-children-in-a-thrift-shop-between-picture-id1303292803?s=612x612"},
{productImage: 'https://media.istockphoto.com/photos/poverty-concept-used-red-shoes-for-children-in-a-thrift-shop-between-picture-id1303292803?s=612x612'},
{productImage: "https://media.istockphoto.com/photos/poverty-concept-used-red-shoes-for-children-in-a-thrift-shop-between-picture-id1303292803?s=612x612"},
{productImage: 'https://media.istockphoto.com/photos/poverty-concept-used-red-shoes-for-children-in-a-thrift-shop-between-picture-id1303292803?s=612x612'},
]
const App = () => {
return (
<SafeAreaView>
<FlatList
numColumns={2}
data={products}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => (<Product product={item} />)}>
</FlatList>
</SafeAreaView>
);
};
export default App;
product.js
import React from 'react';
import { View, Image } from 'react-native';
class Product extends React.Component {
constructor(props){
super(props);
this.state = {
uri : this.props.product.productImage,
errorCount : 0
}
}
passInError(e) {
const { productImage } = this.props.product
if (this.state.errorCount < 3) {
this.setState({uri: productImage, errorCount: ++this.state.errorCount})
console.log(" Corrupt Image URL : " + productImage )
console.log(" Corrupt Image Error Reason : ", JSON.stringify(e) )
console.log (" Corrupt Image Reload Count : ", this.state.errorCount)
}
}
render() {
return (
<View>
<Image
style={{ width: 200, height: 200, borderWidth: 2, }}
source={{ uri:this.state.uri }}
onError = {e => this.passInError(e.nativeEvent) }
key = {this.state.errorCount}
/>
</View>
)
}
}
export default Product;
What code should I write in (onError?: () => void ) function to reload failed images URL ?
Try setting image url in state and update when error on loading image.
product.js
import React from 'react';
import { View } from 'react-native';
import FastImage from 'react-native-fast-image';
class Product extends React.Component {
constructor(props){
super(props);
this.state = {
uri : this.props.product.productImage,
errorCount : 0
}
}
render() {
const { productImage } = this.props.product
return (
<View>
<FastImage
style={{ width: 200, height: 200, borderWidth: 2, }}
source={{ uri:this.state.uri }}
resizeMode={FastImage.resizeMode.contain}
onError={e =>
this.state.errorCount < 3 &&
this.setState(
{uri: '', errorCount: ++this.state.errorCount},
() => this.setState({uri: productImage}),
)
}
/>
</View>
)
}
}
export default Product;
If I understand you correctly, you want to try to load the same image for a 2nd time when there is an error on the 1st try. I would try to re-render the component on Error (even better, wrap the image component with a wrapper component so that the whole Product component is not re-rendered):
const Product = () => {
const [fetchCounter, setFetchCounter] = useState(0);
return (
<img
src={'imageUrl'}
onError={() => {
if (fetchCounter < 1) {
setFetchCounter(fetchCounter++);
}
}}
/>
)
}
I do not know your use case, but you can load a fallback image instead. It could look something like this:
const Product = () => {
const [imageUrl, setImageUrl] = useState('product-img-url');
return (
<img
src={imageUrl}
onError={() => setImageUrl('fallback-img-url')}
/>
)
}

Why does my fetch request return 200 on pc but 400 on ios

I'm communicating to an API to update a state in my application. Everything works fine on PC. But on iOS the network request is 400 and the API does not return anything. Why? I'm running both through CORS anywhere and I've made sure to activate it both on my PC and my iOS device. One of the APIs that I'm communicating with in another file does work on both devices.
Home.js
import React, { useEffect, useState } from "react";
import { View, Text, SafeAreaView, ScrollView } from "react-native";
import { Divider } from "react-native-elements";
import BottomTabs from "../components/home/BottomTabs";
import Categories from "../components/home/Categories";
import HeaderTabs from "../components/home/HeaderTabs";
import RestaurantItems, {
localRestaurants,
} from "../components/home/RestaurantItems";
import SearchBar from "../components/home/SearchBar";
const YELP_API_KEY =
"x";
export default function Home({ navigation }) {
const [restaurantData, setRestaurantData] = useState(localRestaurants);
const [city, setCity] = useState("City");
const [activeTab, setActiveTab] = useState("Delivery");
const getRestaurantsFromYelp = () => {
const yelpUrl = `https://api.yelp.com/v3/businesses/search?term=restaurants&location=${city}`;
const corsUrl = `https://cors-anywhere.herokuapp.com/${yelpUrl}`;
const apiOptions = {
headers: {
Authorization: `Bearer ${YELP_API_KEY}`,
},
};
return fetch(corsUrl, apiOptions)
.then((res) => res.json())
.then((json) => {
console.log("JSON:", json.businesses);
setRestaurantData(json.businesses);
})
.catch((e) => console.log(e));
};
useEffect(() => {
getRestaurantsFromYelp();
}, [city, activeTab]);
useEffect(() => {
console.log("Restaurant Data Updated", restaurantData);
}, [restaurantData]);
return (
<SafeAreaView style={{ backgroundColor: "#eee", flex: 1 }}>
<View style={{ backgroundColor: "white", padding: 15 }}>
<HeaderTabs activeTab={activeTab} setActiveTab={setActiveTab} />
<SearchBar cityHandler={setCity} />
</View>
<ScrollView showsVerticalScrollIndicator={false}>
<Categories />
<RestaurantItems
restaurantData={restaurantData}
navigation={navigation}
/>
</ScrollView>
<Divider width={1} />
<BottomTabs />
</SafeAreaView>
);
}

React-native View-pager setPage is not working on iOS

I'm using react-native-pager-view and I try to setPage on my index change but it doesn't work on iOS devices. Flow is like this that I try to pass the index as a props to my custom ViewPager and I'm using the UseEffect to setPage for my ViewPager which is not working on iOS and I have no idea why.
// #flow
import React, { useEffect, useRef } from 'react';
import { StyleSheet, View, I18nManager } from 'react-native';
import PagerView, { PagerViewOnPageSelectedEvent } from 'react-native-pager-view';
type Props = {
children: React$Node,
index: number,
onIndexChange: (index: number) => void,
};
const MyViewPager = ({ children, index, onIndexChange }: Props) => {
const viewPagerRef = useRef<PagerView>(null);
useEffect(() => {
viewPagerRef.current?.setPage(index);
}, [index]);
const onPageSelect = (e: PagerViewOnPageSelectedEvent) => {
onIndexChange(e.nativeEvent.position);
};
return (
<View style={styles.container}>
<PagerView
ref={viewPagerRef}
style={styles.container}
initialPage={index}
orientation="horizontal"
onPageSelected={onPageSelect}
>
{children}
</PagerView>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default MyViewPager;
the #next version "^6.0.0-rc.0" worked for me
yarn add react-native-pager-view#^6.0.0-rc.0
or if you are using npm
npm i react-native-pager-view#^6.0.0-rc.0
If you have layoutDirection="rtl" prop in PagerView.
Try Removing it e.g
Not working code
<PagerView
initialPage={0}
layoutDirection="rtl"
ref={ref}
scrollEnabled={false} >
Working code for me
<PagerView
initialPage={0}
ref={ref}
scrollEnabled={false} >
This solution worked for me.

Want to pass data to other component - ListView

I have added and imported the sample data. I want to list out data from this file in a list view and I'm passing the data to the Row Component for RenderRow. But getting error saying
Row(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
import React, { Component } from 'react';
import { AppRegistry, View, ListView, Text, StyleSheet } from 'react-native';
import Row from './app/Row';
import data from './app/Data';
export default class ListViewDemo extends Component {
constructor(props) {
super(props);
const rowHasChanged = (r1, r2) => r1 !== r2
const ds = new ListView.DataSource({rowHasChanged});
this.state = {
dataSource: ds.cloneWithRows(data),
};
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={(data) => <Row {...data} />} // Getting error here
/>
);
}
}
AppRegistry.registerComponent('DemoApp',() => ListViewDemo)
These my sample Data.js You can check the data here.
export default data = [
{...}, {...}
];
Row.js:
const Row = (props) => {
<View Style={styles.container}>
<Image source={{ uri: props.picture.large}} />
<Text >
{`${props.name.first} ${props.name.last}`}
</Text>
</View>
}
What would be the problem?
ES6 only returns when there is no explicit blocks:
const cb = (param) => param * 2;
You should explicitly return:
const Row = (props) => {
return (
<View Style={styles.container}>
<Image source={{ uri: props.picture.large}} />
<Text >
{`${props.name.first} ${props.name.last}`}
</Text>
</View>
);
}
Check this answer for further explanation.
Change this Line to
renderRow={(data) => <Row {...data} />}
To This
renderRow={(data) =><Row {...this.props} />}
This may help you to get props in the row Component

Resources