Objects are not valid as a React child (found: object with keys ..) - react-native

I am trying to build a basic app where I fetch some restaurants from yelp api.
I get the error below on iOS and I can't seem to fix it.
Objects are not valid as a React child (found: object with keys {id,
alias, name, image_url, is_closed, url, review_count, categories,
rating, coordinates, transactions, price, location, phone,
display_phone, distance}). If you meant to render a collection of
children, use an array instead.
When I remove the part results={filterResultsByPrice('$')} from <ResultsList> the app works again.
Would appreciate a lot if someone could help.
This is my main screen:
import React, {useState} from 'react';
import { View, Text, StyleSheet } from 'react-native';
import SearchBar from '../component/SearchBar';
import useResults from '../hooks/useResults';
import ResultsList from '../component/ResultsList';
const SearchScreen = () => {
const [term, setTerm] = useState('');
const [searchApi, results, errorMessage] = useResults();
const filterResultsByPrice = (price) => {
return results.filter( result => {
return result.price === price;
});
};
return (
<View>
<SearchBar
term={term}
onTermChange={(newTerm)=> setTerm(newTerm)}
onTermSubmit={searchApi}
/>
{errorMessage ? <Text>{errorMessage}</Text> : null }
<Text>We have found {results.length} results</Text>
<ResultsList results={filterResultsByPrice('$')} title="Cost Effective"/>
<ResultsList results={filterResultsByPrice('$$')} title="Bit Pricier"/>
<ResultsList results={filterResultsByPrice('$$$')} title="Big Spender"/>
</View>
);
};
const styles = StyleSheet.create({});
export default SearchScreen;
This is the component I want to place on the screen:
import React from 'react';
import { View, Text, StyleSheet} from 'react-native';
const ResultsList = ({ title, results }) => {
return (
<View>
<Text style={styles.title}> {title}</Text>
<Text> Results: {results.length} </Text>
</View>
);
};
const styles = StyleSheet.create({
title:
{
fontSize: 18,
fontWeight: 'bold'
}
});
export default ResultsList;
And this is my useResults hook:
import {useEffect, useState } from 'react';
import yelp from '../api/yelp';
export default () => {
const [results, setResults] = useState([]); //default is empty array
const [errorMessage, setErrorMessage] = useState('');
const searchApi = async searchTerm=> {
console.log('Hi there');
try {
const response = await yelp.get('/search', {
params: {
limit: 50,
term: searchTerm,
location: 'san jose'
}
});
setResults(response.data.businesses);
} catch (err) {
setErrorMessage('Something went wrong.');
}
};
useEffect(()=> {
searchApi('pasta');
}, []);
return [searchApi, results, errorMessage];
};

You need to update your ResultsList component to this one, hopefully it will fix your issue permanently:
import React from "react";
import { View, Text, StyleSheet } from "react-native";
const ResultsList = ({ title, results }) => {
return (
<View>
<Text style={styles.title}> {title}</Text>
{results.map(result => (
<Text>Results: {result.length}</Text>
))}
</View>
);
};
const styles = StyleSheet.create({
title: {
fontSize: 18,
fontWeight: "bold"
}
});
export default ResultsList;

Related

Can't find variable: queriesString - React Native Context

The app is for looking up information about product from an api, either by article or ean code.
User can input Article code or EAN in TextInput or scan a barcode and get the information about the product from the api.
The problem im having is i'm not able to pass the search queries from the Textinput to the queriesString in the Context Provider.
This is the error code im getting.
> ReferenceError: Can't find variable: queriesString
For what i'm able to find out the code should work, but since its my first app in react native im most likely missing something.
App
App.js
import { NavigationContainer } from "#react-navigation/native";
import { createNativeStackNavigator } from "#react-navigation/native-stack";
import HomeScreen from "./app/screens/HomeScreen";
import ScannerScreen from "./app/screens/ScannerScreen";
import { queriesContext } from "./app/global/queriesContext";
const Stack = createNativeStackNavigator();
export default function App() {
return (
<>
<queriesContext.Provider value={{ queriesString: "123456789" }}>
{console.log(queriesString + " - From App")}
<NavigationContainer>
<Stack.Navigator initialRouteName='Home' screenOptions={{ headerShown: false }}>
<Stack.Screen name='Home' component={HomeScreen} />
<Stack.Screen name='Scanner' component={ScannerScreen} />
</Stack.Navigator>
</NavigationContainer>
</queriesContext.Provider>
</>
);
}
HomeScreen
HomeScreen.js
import { StyleSheet, Text, View, Image, SafeAreaView, Platform, TextInput, Button, TouchableWithoutFeedback, Keyboard } from "react-native";
import { useNavigation } from "#react-navigation/native";
import React, { useContext, useState, useEffect } from "react";
import ProductScreen from "../global/GetData";
import { queriesContext } from "../global/queriesContext";
export default function HomeScreen() {
const [queriesString, setQueriesString] = useContext(queriesContext);
const [queries, setQueries] = useState(queriesString);
const navigation = useNavigation();
const handleSearch = () => {
setQueriesString(queries);
};
ProductScreen();
//console.log(useState.q);
return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<SafeAreaView style={styles.MainScreen}>
<ProductScreen />
<TextInput style={styles.TextField} editable={true} maxLength='30' numberOfLines='1' placeholder='Art no.' keyboardType='numeric' onChange={(text) => setQueries(text)} />
<Button color='red' title='Search' onPress={handleSearch} />
<View style={styles.BarcodeBox}>
<TouchableWithoutFeedback onPress={() => navigation.navigate("Scanner")}>
<Image style={styles.BarcodeImage} source={require("../assets/barcode.png")} />
</TouchableWithoutFeedback>
</View>
</SafeAreaView>
</TouchableWithoutFeedback>
);
}
const styles = StyleSheet.create({
MainScreen: {.............},
});
ScannerScreen
Not complete since i can't get to pass the value from HomeScreen to context.
ScannerScreen.js
import React, { Component, useState, useEffect } from "react";
import { Text, View, Alert, StyleSheet } from "react-native";
import { BarCodeScanner } from "expo-barcode-scanner";
export default function ScannerScreen() {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
useEffect(() => {
const getBarCodeScannerPermissions = async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === "granted");
};
getBarCodeScannerPermissions();
}, []);
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
Alert.alert("Strekkode", data, [{ text: "Yes", onPress: () => setScanned(false) }, { text: "No" }]);
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<BarCodeScanner onBarCodeScanned={scanned ? undefined : handleBarCodeScanned} style={[StyleSheet.absoluteFill, styles.container]}>
<View style={styles.layerTop} />
<View style={styles.layerCenter}>
<View style={styles.layerLeft} />
<View style={styles.focused} />
<View style={styles.layerRight} />
</View>
<View style={styles.layerBottom} />
</BarCodeScanner>
);
}
const opacity = "rgba(0, 0, 0, .5)";
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
},
layerTop: {
flex: 2,
backgroundColor: opacity,
},
layerCenter: {
flex: 1,
flexDirection: "row",
},
layerLeft: {
flex: 1,
backgroundColor: opacity,
},
focused: {
flex: 10,
},
layerRight: {
flex: 1,
backgroundColor: opacity,
},
layerBottom: {
flex: 2,
backgroundColor: opacity,
},
});
GetData
GetData.js
import { StyleSheet, Text, View, Image, SafeAreaView, Platform, TextInput, Button, TouchableWithoutFeedback, Keyboard } from "react-native";
import React, { useContext, useState, useEffect } from "react";
import { queriesContext } from "./queriesContext";
export default ProductScreen = () => {
const [queriesString] = useContext(queriesContext);
const [isLoading, setLoading] = useState(true);
const [isPromotion, setPromotion] = useState(false);
const [data, setData] = useState({
results: [BEFORE API IS CALLED NOT...],
});
console.log(queriesString + " - From GetData");
useEffect(() => {
fetch(
"SERVER.........",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"x-algolia-agent": "Algolia for JavaScript (4.13.1); Browser; JS Helper (3.10.0)",
"x-algolia-application-id": "***********",
"x-algolia-api-key": "************************",
},
body: JSON.stringify({
requests: [
{
indexName: "prod_products",
params: "query=" + queriesString,
},
],
}),
}
)
.then((respnse) => respnse.json())
.then((json) => setData(json), console.log(data))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
//console.log(data);
//console.log(quaryString);
return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<SafeAreaView style={styles.ProductScreen}>
<View style={styles.LogoBox}>
<Image source={require("../assets/Logo.png")} />
<Image
style={styles.ProductImage}
resizeMode='contain'
source={
isLoading
? require("../assets/fallback_266x266.png")
: {
uri: "https://................/" + data.results[0].hits[0].picture.product,
}
}
/>
</View>
<View>
<View>
<Text style={styles.Title}> {data.results[0].hits[0].name.no} </Text>
<Text style={styles.Desciption}>{data.results[0].hits[0].description.no}</Text>
<Text style={[styles.Text, styles.color]}>{data.results[0].hits[0].potentialPromotionsLabels[5110].text.no}</Text>
<Text style={styles.Text}> Price: {data.results[0].hits[0].code}</Text>
<Text style={styles.Text}> Article No: {data.results[0].hits[0].code}</Text>
<Text style={styles.Text}> EAN: {data.results[0].hits[0].ean}</Text>
</View>
</View>
</SafeAreaView>
</TouchableWithoutFeedback>
);
};
const styles = StyleSheet.create({
color: {................},
});
queriesContext
queriesContext.js
import { createContext } from "react";
export const queriesContext = createContext();
Error
ERROR ReferenceError: Can't find variable: queriesString
This error is located at:
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)
ERROR ReferenceError: Can't find variable: queriesString
This error is located at:
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)
If anyone could help i would greatly appreciate it
I finally got it to work.
Renamed a few things (queriesString, setQueriesString to Quary, setQuary) only to make it easier not to misspell.
I changed the brackets to curly braces in HomeScreen.js and GetData.js as suggested by Fanchen Bao.
In the HomeScreen.js from
export default function HomeScreen() {
const [ Quary, setQuary ] = useContext(queriesContext);
const [queries, setQueries] = useState("0");
To
export default function HomeScreen() {
const { Quary, setQuary } = useContext(queriesContext);
const [queries, setQueries] = useState("0");
And in GetData.js from
export default ProductScreen = () => {
const [ Quary ] = useContext(queriesContext);
to
export default ProductScreen = () => {
const { Quary } = useContext(queriesContext);
Then in the App.js i added a component and useState
export default function App() {
const [Quary, setQuary] = useState("95335");
In GetData i had also imported the context from
import { queriesContext } from "./queriesContext";
This was wrong and i changed this to the correct path
import { queriesContext } from "../global/queriesContext";
After this i still wasn't able to update the context correctly, and i found out that i should use onChangeText instead of onChange in the Textinput.
onChange resulted in the context updating, but the value was not the value in the Textinput field. insted it was returning [object Object].
LOG [object Object]

React Native - searchApi is not a function

I am new in React Native. I try to create a simple searching food restaurant with Yelp. Unfortunately, I get an error:
"searchApi is not a function. (in 'searchApi(term)', 'searchApi' is
"")
Below my code.
useResults.js
import React, { useEffect, useState } from 'react';
import yelp from '../api/yelp';
export default () => {
const [result, setResult] = useState([]);
const [errorMessage, setErrorMessage] = useState('');
const searchApi = async (searchTerm) => {
console.log("hi there");
try {
const response = await yelp.get('/search', {
params: {
limit: 50,
term: searchTerm,
location: 'san jose'
}
});
setErrorMessage(null);
setResult(response.data.businesses);
} catch (err) {
setErrorMessage('Something Went Wrong');
}
};
/*
useEffect(() => {}); //Run the arrow function everytime the component is rendered
useEffect(() => {}, []); // Run the arrow function only when the component is first rendered
useEffect(() => {}, [value]); // Run the arrow function only when the component is first rendered, and when the value is changes
*/
useEffect(() => {
searchApi('pasta');
}, []);
return [searchApi, result, errorMessage];
};
SearchScreen.js
import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import ResultList from '../components/ResultList';
import SearchBar from '../components/SearchBar';
import useResults from '../hooks/useResults';
const SearchScreen = () => {
const [term, setTerm] = useState('');
const [searchApi, result, errorMessage] = useResults();
console.log(result);
return (
<View>
<SearchBar
term={term}
onTermChange={setTerm}
onTermSubmit={() => searchApi(term)}
/>
<View>{errorMessage ? <Text>{errorMessage}</Text> : null}</View>
<Text>We have found {result.length} results</Text>
<ResultList title="Cost Effective" />
<ResultList title="Bit Pricier" />
<ResultList title="Big Spender"/>
</View>
);
};
const styles = StyleSheet.create({
});
export default SearchScreen;
edit :
SearchBar.js
import React from 'react';
import { View, Text, StyleSheet, TextInput } from 'react-native';
import { Feather } from '#expo/vector-icons';
const SearchBar = ({ term, onTermChange, onTermSubmit }) => {
return (
<View style={styles.backgroundStyle}>
<Feather style={styles.iconStyle} name="search" size={30} color="black" />
<TextInput style={styles.inputStyle}
autoCapitalize="none"
autoCorrect={false}
placeholder="Search"
value={term}
onChangeText={onTermChange}
onEndEditing={onTermSubmit}
/>
</View>
)
};
const styles = StyleSheet.create({
backgroundStyle: {
marginTop: 10,
backgroundColor: '#F0EEEE',
height: 50,
borderRadius: 5,
marginHorizontal: 15,
flexDirection: 'row'
},
inputStyle: {
flex: 1,
fontSize: 18,
marginHorizontal: 10
},
iconStyle: {
fontSize: 35,
alignSelf: 'center'
}
});
export default SearchBar;
When I type in search bar and hit done button, I got the error above.
Seems in useResults.js file this: return [searchApi, result, errorMessage]; does not properly return the function. But the result and errorMessage return successfully.
And in this file: SearchScreen.js the error line is shown in here: onTermSubmit={() => searchApi(term)}.
How to fix this?
Try adding a callback to onChangeText.
<TextInput style={styles.inputStyle}
autoCapitalize="none"
autoCorrect={false}
placeholder="Search"
value={term}
onChangeText={() => onTermChange()} // Add fat arrow function here
onEndEditing={onTermSubmit}
/>

react native how can I use two items side by side in modal?

how can I use two items side by side in modal ?
Normally I make it like this:
flex-direction: 'row'
but in modal with flatlist, how I make it ? look at the bottom the picture. I want 2 names side by side.
Code:
import React, { useRef, forwardRef, useEffect } from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, FlatList } from 'react-native';
import { Modalize } from 'react-native-modalize';
import faker from 'faker';
import { useCombinedRefs } from '../../utils/use-combined-refs';
export const SnappingList = forwardRef((_, ref) => {
const modalizeRef = useRef(null);
const contentRef = useRef(null);
const combinedRef = useCombinedRefs(ref, modalizeRef);
const getData = () =>
Array(10)
.fill(0)
.map(_ => ({
name: faker.name.findName(),
email: faker.internet.email(),
image: faker.image.avatar()
}));
const profile_image = faker.image.avatar();
const getHeader = () => {
return (
<View style={s.modalContainer}>
<Text>I AM A HEADER</Text>
</View>)
};
const renderItem = ({ item }) => (
<TouchableOpacity style={s.item}>
<Text style={s.item__name}>{item.name}</Text>
</TouchableOpacity>
);
return (
<Modalize
ref={combinedRef}
contentRef={contentRef}
snapPoint={350}
flatListProps={{
data: getData(),
renderItem: renderItem,
ListHeaderComponent: getHeader(),
keyExtractor: item => item.email,
showsVerticalScrollIndicator: false,
removeClippedSubviews: true,
initialNumToRender: 5
}}
/>
);
});
..............................

FlatList Render issue in react-navigation

I am trying to render a FlatList in the home screen using react-navigation after refresing this error message appears:
invariant violation: Objects are not valid as a React child (found: object with keys {screenProps, navigation}). If you meant to render a collection of children, use an array instead.
//App.js
import React from 'react';
import Navigator from './src/Routes/appRoutes';
import { View, Text, StyleSheet } from 'react-native';
import TodoApp from './src/todoApp';
import SingleTodo from './src/components/singleTodo';
const App = () => {
return (
<Navigator />
);
}
const styles = StyleSheet.create(
{
container: {
padding: 40
}
}
)
export default App;
//FlatList screen
import React, { useState } from 'react';
import { View, FlatList } from 'react-native';
import Todos from './components/todos';
import uuid from 'uuid';
const TodoApp = () => {
const [todo, setTodo] = useState([
{
id: uuid(),
title: "FFFFFFFFF",
desc: "first description"
},
{
id: uuid(),
title: "Second title",
desc: "Second description"
}
]
)
return (
<View>
<FlatList
data={todo}
renderItem={({ item }) =>
<Todos title={item.title} desc={item.desc} />}
keyExtractor={item => item.id}
/>
</View>
);
}
export default TodoApp;
//Routes
import { createStackNavigator } from 'react-navigation-stack';
import Todos from './../components/todos';
import SingleTodo from './../components/singleTodo';
import { createAppContainer } from 'react-navigation';
import { Settings } from './../settings';
const screens = {
Home: {
screen: Todos
},
SingleTodo: {
screen: SingleTodo
}
}
const StackScreens = createStackNavigator(screens);
export default createAppContainer(StackScreens);
//Todos screen
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { NavigationNativeContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const Todos = (props) => {
console.log(props);
const { title, desc } = props;
return (
<View style={styles.container}>
<TouchableOpacity onPress={() => props.navigation.navigate('SingleTodoScreen')}>
<View>{props}</View>
<Text style={styles.listText}>{title}</Text>
</TouchableOpacity>
</View>
)
}
const styles = StyleSheet.create({
container: {
padding: 15,
color: "#000",
borderWidth: 1,
borderColor: "#eee",
},
listText: {
fontSize: 16
}
});
export default Todos;
You need to remove the following line from the code
<View>{props}</View>
props is an object, and you can not write the include the object in your JSX.
So your functional component will be like this.
const Todos = (props) => {
console.log(props);
const { title, desc } = props;
return (
<View style={styles.container}>
<TouchableOpacity onPress={() => props.navigation.navigate('SingleTodoScreen')}>
<Text style={styles.listText}>{title}</Text>
</TouchableOpacity>
</View>
)
}

react native navigation Could not find "store" in either the context or props of "Connect(facebookLogin)

I'm building react native app authentication with facebook login.
I'm using stack navigator and I want to add redux to my app.
I just seperate my files to components and when I use stack navigation with redux I get this error
Could not find "store" in either the context or props of
"Connect(facebookLogin)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(facebookLogin)".
index.android.js
import React, { Component } from 'react';
import { Text, View, StyleSheet, TouchableOpacity, AppRegistry, Image } from 'react-native';
import facebookLogin from './src/components/FacebookLogin';
import Home from './src/components/Home';
import {
StackNavigator,
} from 'react-navigation';
const App = StackNavigator({
Home: { screen: facebookLogin },
HomePage: {screen:Home},
})
AppRegistry.registerComponent('facebookLogin', () => App);
FacebookLogin.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
* #flow
*/
import React, { Component } from 'react';
import { Text, View, StyleSheet, TouchableOpacity, AppRegistry, Image } from 'react-native';
import FBSDK, { LoginManager, GraphRequest, GraphRequestManager } from 'react-native-fbsdk';
import Icon from 'react-native-vector-icons/FontAwesome';
// redux
import { Provider } from 'react-redux';
import { connect } from 'react-redux';
import { createStore } from 'redux';
import reducers from '../reducers/ProfileReducers';
const store = createStore(reducers, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
class facebookLogin extends Component {
constructor(props) {
super(props);
this.state = {
result: null
}
}
_fbAuth() {
const { navigate } = this.props.navigation;
LoginManager.logInWithReadPermissions(['public_profile','user_birthday']).then((result) => {
if (result.isCancelled) {
console.log('Login was canclled');
}
else {
console.log(result);
const infoRequest = new GraphRequest(
'/me?fields=id,name,picture.width(800).height(800),gender,birthday,first_name,last_name',
null,
(error, result) => {
if (error) {
alert('Error fetching data: ' + error.toString());
} else {
console.log(result);
this.setState({ result });
navigate('HomePage');
}
}
);
// Start the graph request.
new GraphRequestManager().addRequest(infoRequest).start();
}
}, function (error) {
console.log('An error occured:' + error);
})
}
getProfileData() {
const { ImageStyle } = styles;
if (this.state.result) {
return (
<View>
{this.state.result.picture ? <Image style={ImageStyle} source={{ uri: this.state.result.picture.data.url }}></Image> : null}
<Text> first name: {this.state.result.first_name} </Text>
<Text> Last name: {this.state.result.last_name} </Text>
<Text> Gender {this.state.result.gender} </Text>
</View>
)
}
return null;
}
render() {
return (
<Provider store = {store}>
<View style={styles.container}>
<Icon.Button name="facebook" backgroundColor="#3b5998" onPress={() => { this._fbAuth() }}>
<Text style={{fontFamily: 'Arial', fontSize: 15, color:'white'}}>Login with Facebook</Text>
</Icon.Button>
{this.getProfileData()}
</View>
</Provider>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
ImageStyle:{
borderRadius:80,
width:100,
height:100
}
});
const mapStateToProps = (state) => {
return
{ profile: state.profile};
}
export default connect(mapStateToProps)(facebookLogin);
when it was only one component in index.android.js it works fine without any error but when I seperate it to some components using stack navigation I get this error.
my profileReducers
var profile = {
name :'',
email:'',
photo:''
}
const initialState = {
profile,
};
export default (state = initialState, action) => {
console.log("state");
switch (action.type) {
case 'INSERT_PROFILE_DETAILS':
return {
profile: action.payload
}
case 'GET_PROFILE_DETAILS': {
return state;
}
default:
return state;
}
}
Try setting up redux in index.android.js instead so it looks something like this:
// Set up redux store above
const Navigator = StackNavigator({
Home: { screen: facebookLogin },
HomePage: { screen: Home },
});
const App = () => (
<Provider store={store}>
<Navigator />
</Provider>
);
AppRegistry.registerComponent('facebookLogin', () => App);