White screen on publishing app on Apple store when revienwing - react-native

Warning: Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
in RCTText (created by Text)
in Text
in Text (created by BottomNavigation)
in RCTView (created by View)
in View (created by AnimatedComponent)
in AnimatedComponent
in AnimatedComponentWrapper (created by BottomNavigation)
in RCTView (created by View)
in View (created by AnimatedComponent)
in AnimatedComponent
in AnimatedComponentWrapper (created by BottomNavigation)
in RCTView (created by View)
in View (created by BottomNavigation)
in RCTView (created by View)
in View (created by Touchable)
in TouchableWithoutFeedback (created by Touchable)
in Touchable (created by BottomNavigation)
in RCTView (created by View)
in View (created by BottomNavigation)
in RCTView (created by View)
in View (created by AnimatedComponent)
in AnimatedComponent
in AnimatedComponentWrapper (created by BottomNavigation)
in RCTView (created by View)
in View (created by AnimatedComponent)
in AnimatedComponent
in AnimatedComponentWrapper
in RCTView (created by View)
in View (created by AnimatedComponent)
in AnimatedComponent
in AnimatedComponentWrapper
in RCTView (created by View)
in View (created by AnimatedComponent)
in AnimatedComponent
in AnimatedComponentWrapper
in Unknown (created by BottomNavigation)
in RCTView (created by View)
in View (created by BottomNavigation)
in BottomNavigation
in ThemedComponent (created by withTheme(BottomNavigation))
in withTheme(BottomNavigation) (created by MaterialBottomTabViewInner)
in MaterialBottomTabViewInner (created by MaterialBottomTabView)
in RNCSafeAreaProvider (created by SafeAreaProvider)
in SafeAreaProvider (created by SafeAreaInsetsContext)
in SafeAreaProviderCompat (created by MaterialBottomTabView)
in MaterialBottomTabView (created by MaterialBottomTabNavigator)
in PreventRemoveProvider (created by NavigationContent)
in NavigationContent
in Unknown (created by MaterialBottomTabNavigator)
in MaterialBottomTabNavigator (created by App)
in EnsureSingleNavigator
in BaseNavigationContainer
in ThemeProvider
in NavigationContainerInner (created by App)
in App (created by withDevTools(App))
in withDevTools(App)
in RCTView (created by View)
in View (created by AppContainer)
in RCTView (created by View)
in View (created by AppContainer)
in AppContainer
in main(RootComponent)
I tried to publish my app on Apple Store and they told me after splashscreen, a white screen appears and on my phone everything is getting fine.
bellow my code :
import React,{useEffect} from 'react';
import { ImageBackground,Text,StyleSheet,View,TouchableOpacity,Image,FlatList} from 'react-native';
import * as Animatable from 'react-native-animatable';
import Include_entete from '../includes/Include_entete';
import Couleurs from '../composants/Couleurs';
import { LinearGradient } from 'expo-linear-gradient';
import {expo} from '../app.json';
import { Ionicons } from '#expo/vector-icons';
import { MaterialCommunityIcons } from '#expo/vector-icons';
//import * as Device from 'expo-device';
export default function Fenetre_accueil({navigation})
{
const [isLoading,setIsLoading] = React.useState(true);
const [data, setData] = React.useState({hits:[]});
useEffect(() =>
{
setIsLoading(true);
setTimeout(async() => {
fetch("https://www.xxxxxx.com/application/app-recueil-sct/last_four_song.php", {method: "GET"})
.then((response) => response.json())
.then((responseJson) =>
{
setData({hits:responseJson});
})
setIsLoading(false);
},1000);
}, []);
if(isLoading)
{
return(
<Animatable.View style={{flex:1,justifyContent:'center',alignItems:'center'}} animation="bounceIn">
<RemotImage
uri={"https://fxxxxxxx.com/ressources/images/logo.png"}
desireWidth={200}
/>
</Animatable.View>
);
}
return(
<Animatable.View animation="bounceInDown" style={{flex:1}}>
<Include_entete />
<ImageBackground imageStyle={{opacity: 0.2}} style={{flex:1,justifyContent:'center',alignSelf:'stretch'}} source={require('./../images/eagle1.jpeg')} resizeMode='cover'>
<View style={styles.container}>
<FlatList
ListHeaderComponent={
<View>
<Text style={{color:Couleurs.text_info,fontSize:20,marginBottom:5,marginLeft:5}}>Bienvenue</Text>
<TouchableOpacity onPress={() => {navigation.navigate('Search',{search:' '})}} style={[styles.boxshadow,styles.card]}>
<ImageBackground source={{uri:'https://xxxxxxxx.com/ressources/images/bible.jpg'}} resizeMode='cover' style={{minHeight:200}}>
<LinearGradient colors={['rgba(0,0,0,0.2)','rgba(0,0,0,0.8)']} style={{minHeight:200,padding:5}}>
<View style={{flexDirection:'row'}}>
<MaterialCommunityIcons name="book-open-page-variant" size={45} color="#fff" style={{marginRight:5}}/>
<Text style={{fontSize:35,color:"#FDF2E9"}}>Recueil SCT</Text>
</View>
<Text style={{color:'#FDF2E9',fontSize:16,marginTop:10,paddingHorizontal:2}}>Cette application vous donne accès à tout le guide de cantiques de l'Eglise Soleil Couchant Tabernacle.</Text>
<View style={{flexDirection:'row-reverse',borderTopColor:'#FDF2E9',borderTopWidth:1,marginTop:20}}>
<Ionicons name="arrow-forward-circle-sharp" size={40} color="#FDF2E9" />
<Text style={{fontSize:16,color:"#FDF2E9",marginRight:5,marginTop:7}}>Accéder à tous nos Cantiques</Text>
</View>
</LinearGradient>
</ImageBackground>
</TouchableOpacity>
<Text style={{color:Couleurs.text_info,fontSize:20,marginBottom:5,marginLeft:5}}>Dernières mise à jour</Text>
</View>
}
data={data.hits} showsVerticalScrollIndicator={false} nestedScrollEnabled={true}
renderItem={({item,index}) =>
(
<TouchableOpacity onPress={() => {navigation.navigate('Chant',{Id:item.id})}} style={[styles.boxshadow,styles.card]}>
<ImageBackground source={{uri:'https://xxxxxxxx.com/ressources/images/jesus.jpg'}} resizeMode='cover' style={{minHeight:200}}>
<LinearGradient colors={['rgba(0,0,0,0.2)','rgba(0,0,0,0.8)']} style={{minHeight:200,padding:5}}>
<View style={{flexDirection:'row'}}>
<MaterialCommunityIcons name="microphone-variant" size={45} color="#fff" />
<Text style={{fontSize:35,color:"#FDF2E9"}}>Chant : #{item.num}</Text>
</View>
<Text style={{color:'#FDF2E9',fontSize:16,marginTop:10,paddingHorizontal:2}}>{item.chant.substring(0,100).replace(/\n|\r/g,' ')}...</Text>
<View style={{flexDirection:'row-reverse',borderTopColor:'#FDF2E9',borderTopWidth:1,marginTop:20}}>
<Ionicons name="arrow-forward-circle-sharp" size={40} color="#FDF2E9" />
<Text style={{fontSize:16,color:"#FDF2E9",marginRight:5,marginTop:7}}>Consulter</Text>
</View>
</LinearGradient>
</ImageBackground>
</TouchableOpacity>
)}
keyExtractor = {( item, index ) => index.toString() }
ListFooterComponent={
<View>
<Text style={styles.text_footer}>version {expo.version}</Text>
<Text style={{fontSize:9,color:Couleurs.text_muted,textAlign:'center'}}>Développé par <Text style={{fontWeight:'bold'}}>ifluxe</Text></Text>
<Text style={{fontSize:9,textAlign:'center'}}><Text style={{fontWeight:'700'}}>Fruxgroupe</Text> en parténariat avec <Text style={{fontWeight:'700'}}>Soleil Couchant Tabernacle</Text></Text>
</View>
}
/>
</View>
</ImageBackground>
</Animatable.View>
);
}
const styles = StyleSheet.create({
text_footer:{textAlign:'center',marginTop:5,borderTopWidth:1,borderTopColor:"#7F8C8D",fontSize:10,paddingTop:1},
container:{padding:10},
card:{marginBottom:20},
boxshadow:{shadowColor:Couleurs.text_muted,elevation:7},
});
const RemotImage = ({uri,desireWidth}) => {
const [desiredHeight, setdesiredHeight] = React.useState(0)
Image.getSize(uri, (width,height) =>
{
setdesiredHeight(desireWidth/width*height)
})
return (
<Image source={{uri}} style={{width:desireWidth,height:desiredHeight}}/>
)
};

Related

Undefined Is Not A Function (React Navigation Bottom Tab Navigator)

I am building bottom tabs navigator from react navigation v6 in react native mobile app but encountered an error.
ERROR TypeError: undefined is not a function
This error is located at:
in MaybeScreenContainer (created by BottomTabView)
in RNCSafeAreaProvider (created by SafeAreaProvider)
in SafeAreaProvider (created by SafeAreaInsetsContext)
in SafeAreaProviderCompat (created by BottomTabView)
in BottomTabView (created by BottomTabNavigator)
in PreventRemoveProvider (created by NavigationContent)
in NavigationContent
in Unknown (created by BottomTabNavigator)
in BottomTabNavigator (created by tabNavigation)
in EnsureSingleNavigator
in BaseNavigationContainer
in ThemeProvider
in NavigationContainerInner (created by tabNavigation)
in tabNavigation (created by App)
in RCTView (created by View)
in View (created by App)
in authState (created by App)
in App
in RCTView (created by View)
in View (created by AppContainer)
in RCTView (created by View)
in View (created by AppContainer)
in AppContainer
in KFC(RootComponent), js engine: hermes
The Code Of Tab Navigator That I have written for tabs. I am using physical device for test:
import React from 'react';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import Home from '../views/Home';
import Auth from '../views/Auth';
import Bucket from '../views/Bucket';
import Menu from '../views/Menu';
import {NavigationContainer} from '#react-navigation/native';
const Tab = createBottomTabNavigator();
export default function tabNavigation() {
return (
<NavigationContainer>
<Tab.Navigator initialRouteName="home">
<Tab.Screen name="home" component={Home} />
<Tab.Screen name="auth" component={Auth} />
<Tab.Screen name="bucket" component={Bucket} />
<Tab.Screen name="menu" component={Menu} />
</Tab.Navigator>
</NavigationContainer>
);
}
Ran into the same error. Turns out, bottom tabs navigator also needs react-native-screens.
yarn add react-native-screens | npm install react-native-screens should do the trick. You may have to re-build or clear your cache as well.
Try to replace your screen one by one and you will find your trouble maker
import React from 'react';
import { View, Text } from 'react-native'
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
//import Home from '../views/Home';
//import Auth from '../views/Auth';
//import Bucket from '../views/Bucket';
//import Menu from '../views/Menu';
import {NavigationContainer} from '#react-navigation/native';
const Tab = createBottomTabNavigator();
function Dummy() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Dummy</Text>
</View>
);
}
export default function tabNavigation() {
return (
<NavigationContainer>
<Tab.Navigator initialRouteName="home">
<Tab.Screen name="home" component={Dummy} />
<Tab.Screen name="auth" component={Dummy} />
<Tab.Screen name="bucket" component={Dummy} />
<Tab.Screen name="menu" component={Dummy} />
</Tab.Navigator>
</NavigationContainer>
);
}

React.createElement: type is invalid expected a string(for built-in components)or a class/function(for composite components)but got: %s.%s%s,

React.createElement: type is invalid -- expected a string (for
built-in components) or a class/function (for composite components)
but got: %s.%s%s, undefined, You likely forgot to export your
component from the file it's defined in, or you might have mixed up
default and named imports.
Check your code at App.js:10.,
in App (created by ExpoRoot)
in RCTView (at NativeAppearance.tsx:4)
in FallbackAppearanceProvider (at src/index.tsx:70)
in AppearanceProvider (created by ExpoRoot)
in RootErrorBoundary (created by ExpoRoot)
in ExpoRoot (at renderApplication.js:45)
in RCTView (at AppContainer.js:109)
in RCTView (at AppContainer.js:135)
in AppContainer (at renderApplication.js:39)
export code is there. What is the problem in the code please?
App.js code
import { StatusBar } from "expo-status-bar";
import React from "react";
import { StyleSheet, Text, View } from "react-native";
import { HotelComp } from "./components/hotel";
export default function App() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<HotelComp />
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
hotel.js code
import React, { Component } from "react";
import { Text, View } from "react-native";
export class hotel extends Component {
render() {
return (
<View>
<Text> hotel Component </Text>
</View>
);
}
}
export default hotel;
You have the class exported twice, and you are importing hotelComp, not hotel. Try this for hotel.js:
export default class hotel extends Component {
render() {
return (
<View>
<Text> hotel Component </Text>
</View>
);
}
}
And import it like this (assuming the hotel.js file is in the /components folder):
import hotel from "./components/hotel"

nested navigation question - how to export BottomTabNavigator

I am stuck with a problem with my bottomTabNavigator that should load the main pages for the app (main, kowops, wallet, scan) which is nested in a stack navigator that handles the login / registration screens (login, register, forget password).
This is my main.js
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import Scan from './Scan';
import Kowops from './Kowops';
import Wallet from './Wallet';
export default class Main extends Component {
render() {
return (
<View style={styles.container}>
<View style={{alignItems: 'center'}}>
<Text style={styles.plainText} onPress={() => this.props.navigation.navigate('Register')}>
This is the main page, return to registration
</Text>
<View style={{height:5}}></View>
</View>
</View>
)
}
}
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Main" component={Main} />
<Tab.Screen name="Scan" component={Scan} />
<Tab.Screen name="Wallet" component={Wallet} />
<Tab.Screen name="Kowops" component={Kowops} />
</Tab.Navigator>
</NavigationContainer>
);
}
export function BottomNav() {
return (
<NavigationContainer>
<MyTabs />
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 2,
backgroundColor:'#ffffff',
padding: 10,
alignItems: 'stretch',
justifyContent: 'space-around'
},
logoContainer: {
height: 120,
padding: 10,
alignItems: 'center' ,
justifyContent: 'flex-end'
},
logo: {
height: 50,
width: 165
},
formContainer: {
flex:1,
alignItems: 'center' ,
justifyContent: 'center'
},
buttonContainer: {
padding: 10,
marginBottom: 20,
width: 250,
alignItems: 'center',
backgroundColor: '#c5e1a5'
},
inputTextField: {
alignItems: 'center',
justifyContent: 'space-between',
padding: 10,
height: 40,
width: 250,
marginBottom: 10,
fontSize: 16,
borderBottomWidth : 1.0,
},
plainText: {
fontSize: 16,
marginBottom: 5,
color: '#59616e',
textDecorationLine: 'underline',
},
});
And this is my app.js with the login stack navigator
/**
* Load navigation
* Check login state
* Navigate to register.js if no valid session is detected
* Navigate to home.je is a valid session is detected
*/
import 'react-native-gesture-handler';
import React from 'react';
import Register from './register';
import Login from './login';
import main from './main';
import ForgotPassword from './forgotPassword';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Register" screenOptions={{headerShown: false}}>
<Stack.Screen name="Register" component={Register} />
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="ForgotPassword" component={ForgotPassword} />
<Stack.Screen name="Main" component={main} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
Now my bottomnavigation doesn't show on the main page. Ai already tried to replace the default in main.js like this
export class Main extends Component
&
export default function BottomNav()
But then I get
a nasty error:
Error: Looks like you have nested a 'NavigationContainer' inside another. Normally you need only one container at the root of the app, so this was probably an error. If this was intentional, pass 'independent={true}' explicitely. Note that this will make the child navigators disconnected from the parent and you won't be able to navigate between them.
This error is located at:
in ForwardRef(BaseNavigationContainer) (at NavigationContainer.tsx:66)
in ThemeProvider (at NavigationContainer.tsx:65)
in ForwardRef(NavigationContainer) (at main.js:42)
in BottomNav (at SceneView.tsx:98)
in StaticContainer
in StaticContainer (at SceneView.tsx:89)
in EnsureSingleNavigator (at SceneView.tsx:88)
in SceneView (at useDescriptors.tsx:125)
in RCTView (at CardContainer.tsx:199)
in RCTView (at CardContainer.tsx:198)
in RCTView (at CardSheet.tsx:33)
in ForwardRef(CardSheet) (at Card.tsx:526)
in RCTView (at createAnimatedComponent.js:144)
in AnimatedComponent (at createAnimatedComponent.js:194)
in ForwardRef(AnimatedComponentWrapper) (at Card.tsx:508)
in PanGestureHandler (at GestureHandler.native.tsx:13)
in PanGestureHandler (at Card.tsx:502)
in RCTView (at createAnimatedComponent.js:144)
in AnimatedComponent (at createAnimatedComponent.js:194)
in ForwardRef(AnimatedComponentWrapper) (at Card.tsx:498)
in RCTView (at Card.tsx:492)
in Card (at CardContainer.tsx:164)
in CardContainer (at CardStack.tsx:497)
in RCTView (at Screens.tsx:70)
in MaybeScreen (at CardStack.tsx:490)
in RCTView (at Screens.tsx:48)
in MaybeScreenContainer (at CardStack.tsx:388)
in CardStack (at StackView.tsx:433)
in KeyboardManager (at StackView.tsx:431)
in RNCSafeAreaView (at src/index.tsx:28)
in SafeAreaProvider (at SafeAreaProviderCompat.tsx:42)
in SafeAreaProviderCompat (at StackView.tsx:428)
in RCTView (at StackView.tsx:427)
in StackView (at createStackNavigator.tsx:82)
in StackNavigator (at App.js:21)
in EnsureSingleNavigator (at BaseNavigationContainer.tsx:288)
in ForwardRef(BaseNavigationContainer) (at NavigationContainer.tsx:66)
in ThemeProvider (at NavigationContainer.tsx:65)
in ForwardRef(NavigationContainer) (at App.js:20)
in App (at renderApplication.js:45)
in RCTView (at AppContainer.js:109)
in RCTView (at AppContainer.js:135)
in AppContainer (at renderApplication.js:39)
BaseNavigationContainer
BaseNavigationContainer.tsx:114:12
renderWithHooks
ReactNativeRenderer-dev.js:10989:26
updateForwardRef
ReactNativeRenderer-dev.js:13060:34
invokeGuardedCallbackImpl
ReactNativeRenderer-dev.js:286:4
invokeGuardedCallback
ReactNativeRenderer-dev.js:497:2
beginWork$$1
ReactNativeRenderer-dev.js:22028:27
performUnitOfWork
ReactNativeRenderer-dev.js:20871:23
workLoopSync
ReactNativeRenderer-dev.js:20848:38
performSyncWorkOnRoot
ReactNativeRenderer-dev.js:20456:22
performSyncWorkOnRoot
[native code]:0
runWithPriority$argument_1
ReactNativeRenderer-dev.js:5703:31
unstable_runWithPriority
scheduler.development.js:818:23
flushSyncCallbackQueueImpl
ReactNativeRenderer-dev.js:5698:21
flushSyncCallbackQueue
ReactNativeRenderer-dev.js:5686:28
flushSync
ReactNativeRenderer-dev.js:20630:26
scheduleRefresh
ReactNativeRenderer-dev.js:6492:13
mountedRoots.forEach$argument_0
react-refresh-runtime.development.js:218:8
forEach
[native code]:0
performReactRefresh
react-refresh-runtime.development.js:210:4
Refresh.performReactRefresh
setUpReactRefresh.js:43:6
setTimeout$argument_0
require.js:627:10
_callTimer
JSTimers.js:135:14
callTimers
JSTimers.js:387:16
__callFunction
MessageQueue.js:425:19
__guard$argument_0
MessageQueue.js:112:6
__guard
MessageQueue.js:373:10
callFunctionReturnFlushedQueue
MessageQueue.js:111:4
callFunctionReturnFlushedQueue
[native code]:0
Does anyone have an idea on how to fix this?
Best,
Tim
change
function MyTabs() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Main" component={Main} />
<Tab.Screen name="Scan" component={Scan} />
<Tab.Screen name="Wallet" component={Wallet} />
<Tab.Screen name="Kowops" component={Kowops} />
</Tab.Navigator>
</NavigationContainer>
);
}
export function BottomNav() {
return (
<NavigationContainer>
<MyTabs />
</NavigationContainer>
);
}
to
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Main" component={Main} />
<Tab.Screen name="Scan" component={Scan} />
<Tab.Screen name="Wallet" component={Wallet} />
<Tab.Screen name="Kowops" component={Kowops} />
</Tab.Navigator>
);
}
export function BottomNav() {
return (
<MyTabs />
);
}
you are nesting NavigationContainer remove NavigationContainers as I mentioned.
Hope this helps!

Invariant Violation: The navigation prop is missing for this navigator. error on expo

My problem is the same with this one but I have difficulty what should I do if I'm using store provider like this:
const AppNavigator = createSwitchNavigator(
{
Loading: MainLoadingScreen,
App: MainNavigator,
Auth: AuthStack,
Signup: SignupStack
},
{
initialRouteName: 'Loading',
}
);
const App = () => {
return (
<Provider store={store}>
<View style={styles.container}>
<AppNavigator />
</View>
</Provider>
);
};
export default App;
I'm getting this error:
Invariant Violation: The navigation prop is missing for this navigator. In react-navigation 3 you must set up your app container directly. More info: https://reactnavigation.org/docs/en/app-containers.html
This error is located at:
in Navigator (at App.js:114)
in RCTView (at View.js:45)
in View (at App.js:113)
in Provider (at App.js:112)
in App (at withExpoRoot.js:20)
in RootErrorBoundary (at withExpoRoot.js:19)
in ExpoRootComponent (at renderApplication.js:35)
in RCTView (at View.js:45)
in View (at AppContainer.js:98)
in RCTView (at View.js:45)
in View (at AppContainer.js:115)
in AppContainer (at renderApplication.js:34)
- node_modules\#react-navigation\core\lib\module\navigators\createNavigator.js:1:1637 in getDerivedStateFromProps
- node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:6896:46 in applyDerivedStateFromProps
- ... 20 more stack frames from framework internals
How do I convert my code so I can use the format shown here? :
const App = createAppContainer(AppNavigator)
Wrap your switch navigator with createAppContainer:
const MainSwitch = createSwitchNavigator(
{
Loading: MainLoadingScreen,
App: MainNavigator,
Auth: AuthStack,
Signup: SignupStack
},
{
initialRouteName: 'Loading',
}
);
const AppNavigator = createAppContainer(MainSwitch)
export default App = () => {
return (
<Provider store={store}>
<View style={styles.container}>
<AppNavigator />
</View>
</Provider>
);
};
Make it a function and assign it to the value of Const.
const App = function Appfunc() {
return (
<Provider store={store}>
<View style={styles.container}>
<AppNavigator />
</View>
</Provider>
);
}
const AppContainer = createAppContainer(AppNavigator)
export default AppContainer

react-native search bar and flatList issue

can someone please help me troubleshoot?
I am trying to search through a local JSON file and return the relevant data. My JSON file contains a restaurant name and restaurant type.
I don't understand where the issue may be coming from. When I comment out ListHeadComponent={this.renderHeader}, there is no error; however, nothing will display if I comment that out.
The issue I am getting is:
Invariant Violation: Invariant Violation: Tried to get frame for out of range index NaN
This error is located at:
in VirtualizedList (at FlatList.js:662)
in FlatList (at SearchScreen.js:75)
in RCTView (at View.js:44)
in SearchScreen (created by SceneView)
in SceneView (at StackViewLayout.js:795)
in RCTView (at View.js:44)
in AnimatedComponent (at StackViewCard.js:69)
in RCTView (at View.js:44)
in AnimatedComponent (at screens.native.js:59)
in Screen (at StackViewCard.js:57)
in Card (at createPointerEventsContainer.js:27)
in Container (at StackViewLayout.js:860)
in RCTView (at View.js:44)
in ScreenContainer (at StackViewLayout.js:311)
in RCTView (at View.js:44)
in AnimatedComponent (at StackViewLayout.js:307)
in Handler (at StackViewLayout.js:300)
in StackViewLayout (at withOrientation.js:30)
in withOrientation (at StackView.js:79)
in RCTView (at View.js:44)
in Transitioner (at StackView.js:22)
in StackView (created by Navigator)
in Navigator (at createKeyboardAwareNavigator.js:12)
in KeyboardAwareNavigator (created by SceneView)
in SceneView (at createTabNavigator.js:39)
in RCTView (at View.js:44)
in RCTView (at View.js:44)
in ResourceSavingScene (at createBottomTabNavigator.js:113)
in RCTView (at View.js:44)
in ScreenContainer (at createBottomTabNavigator.js:103)
in RCTView (at View.js:44)
in TabNavigationView (at createTabNavigator.js:197)
in NavigationView (created by Navigator)
in Navigator (created by SceneView)
in SceneView (created by SwitchView)
in SwitchView (created by Navigator)
in Navigator (at createAppContainer.js:388)
in NavigationContainer (at App.js:24)
in RCTView (at View.js:44)
in App (at withExpoRoot.js:22)
in RootErrorBoundary (at withExpoRoot.js:21)
in ExpoRootComponent (at renderApplication.js:34)
in RCTView (at View.js:44)
in RCTView (at View.js:44)
in AppContainer (at renderApplication.js:33)
This error is located at:
in NavigationContainer (at App.js:24)
in RCTView (at View.js:44)
in App (at withExpoRoot.js:22)
in RootErrorBoundary (at withExpoRoot.js:21)
in ExpoRootComponent (at renderApplication.js:34)
in RCTView (at View.js:44)
in RCTView (at View.js:44)
in AppContainer (at renderApplication.js:33)
The code in my .js file is:
import React from 'react';
import { ExpoConfigView } from '#expo/samples';
import { View, Text, FlatList, ActivityIndicator} from 'react-native';
import { SearchBar } from 'react-native-elements';
import restaurantList from '../assets/files/search.json';
export default class SearchScreen extends React.Component {
static navigationOptions = {
title: 'Search for Restaurants',
};
constructor() {
super();
this.state = {
loading: false,
data: {restaurantList},
error: null,
};
this.arrayholder = [];
}
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: '86%',
backgroundColor: '#CED0CE',
marginLeft: '14%',
}}
/>
);
};
searchFilterFunction = text =>{
this.setState({
value: text,
});
const newData = this.arrayholder.filter(item => {
const itemData = `${item.name.toUpperCase()}
${item.type.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
})
this.setState({
data: newData,
});
};
renderHeader = () => {
return (
<SearchBar
placeholder="Type..."
value={this.state.value}
onChange={text => this.searchFilterFunction(text)}
/>
);
};
render() {
if (this.state.loading) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<ActivityIndicator />
</View>
);
}
return (
<View>
<FlatList
data={this.state.data}
renderItem={({ item }) => (
<Text>{item.name} {item.type}</Text>
)}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
/>
</View>
);
}
}
Here is my json file
[
{
"name": "Shake Shack",
"type":"american"
},
{
"name": "BonChon Chicken",
"type": "korean"
},
{
"name": "Starbucks",
"type:": "cafe"
}
]
This is a really good start. However, there are a couple of issues with your code. So let's go through it and see where we can make some improvements.
Constructor
Firstly in your constructor you are making the data an object rather than array. FlatLists do not work with objects they work with arrays so this is going to immediately cause you problems. You really need to remove the {} from around the restaurantList.
constructor() {
super();
this.state = {
loading: false,
data: {restaurantList}, // You shouldn't have {} around the restaurantList
error: null,
};
this.arrayholder = []; // we also don't need this
}
You should update your constructor to this
constructor (props) {
super(props);
this.state = {
loading: false,
data: restaurantList, // notice we have no {} around restaurantList
error: null,
value: ''
};
}
renderHeader
In your renderHeader function you are using onChange rather than onChangeText. onChange returns an object, but you want the text that has been put into the search bar. You need to update your renderHeader function to be like this.
renderHeader = () => {
return (
<SearchBar
placeholder="Type..."
value={this.state.value}
onChangeText={text => this.searchFilterFunction(text)} // now we are using the correct function to capture the text
/>
);
};
searchFilterFunction
There are several issues with this function. Firstly you are looking at this.arrayholder which is empty. We don't actually need an additional array to hold the data as we can just use the restaurantList that we imported earlier. Secondly you are using indexOf on a string it is better to use includes.
searchFilterFunction = text => {
this.setState({
value: text
});
const newData = restaurantList.filter(item => {
const itemData = `${item.name.toUpperCase()} ${item.type.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.includes(textData); // this will return true if our itemData contains the textData
});
this.setState({
data: newData
});
};
FlatList
In your FlatList you should use the extraData prop as this will allow the FlatList to update when the underlying data changes. You should also add a keyExtractor.
<FlatList
keyExtractor={(item, index) => `${index}`}
extraData={this.state} // <- add this prop
data={this.state.data}
renderItem={({ item }) => (
<Text>{item.name} {item.type}</Text>
)}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
/>
Putting it all together
So if we put this all together, adding a mock of data so that we can check it works. We should get something like this.
// mock the data as you didn't provide an example
const restaurantList = [
{
type: 'Italian',
name: 'DiMaggio'
},
{
type: 'Greek',
name: 'Athena'
}
];
export default class SearchScreen extends React.Component {
static navigationOptions = {
title: 'Search for Restaurants'
};
constructor (props) {
super(props);
this.state = {
loading: false,
data: restaurantList,
error: null,
value: ''
};
}
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: '86%',
backgroundColor: '#CED0CE',
marginLeft: '14%'
}}
/>
);
};
searchFilterFunction = text => {
this.setState({
value: text
});
const newData = restaurantList.filter(item => {
const itemData = `${item.name.toUpperCase()} ${item.type.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.includes(textData);
});
this.setState({
data: newData
});
};
renderHeader = () => {
return (
<SearchBar
placeholder="Type..."
value={this.state.value}
onChangeText={text => this.searchFilterFunction(text)}
/>
);
};
render () {
if (this.state.loading) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<ActivityIndicator />
</View>
);
} else {
return (
<View style={styles.container}>
<FlatList
keyExtractor={(item, index) => `${index}`}
extraData={this.state}
data={this.state.data}
renderItem={({ item }) => (
<Text>{item.name} {item.type}</Text>
)}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
/>
</View>
);
}
}
}
Snack
You can see it working at the following snack https://snack.expo.io/#andypandy/flatlist-with-search