ReferenceError: Can't find variable: styles - reactjs

In my react-native project I experienced the above error
My App.js file:
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
//Screens
import Header from './Shared/Header'
import ProductContainer from './Screens/Products/ProductContainer'
export default function App() {
return (
<View style={styles.container}>
<Header />
<ProductContainer />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
My ProductCotainer.js file:
import React, { useState, useEffect } from 'react'
import { View, StyleSheet, ActivityIndicator, FlatList} from 'react-native'
import ProductList from './ProductList';
const data = require('../../assets/data/products.json');
const ProductContainer = () => {
const [products, setProducts ] = useState([]);
useEffect(() => {
setProducts(data);
return () => {
setProducts([])
}
}, [])
return (
<View style={styles.container}>
<Text>Product Container</Text>
<View style={styles.listContainer}>
<FlatList
data={products}
numColumns={2}
renderItem={({item}) => <ProductList
key={item.id}
item={item}/>}
keyExtractor={item => item.name}
/>
</View>
</View>
)
}
export default ProductContainer;
Please help me to solve this issue
Thanks in advance

You did not define the styles in the ProductCotainer.js file.
In order to use the styles you have 2 options:
Define it in each file that uses it. Which can be pretty hard to maintain in case of a medium/large app that has lots of common styles.
Define a style file that gets imported in each file that uses the styles. This would be a good starting point

Related

I am getting maximum depth exceeded while running react native code

import { StyleSheet, Text, View, ImageBackground, SafeAreaView } from 'react-native';
import react, {useState} from 'react';
import InputComponent from './sharedComponent/InputComponent';
import ButtonComponent from './sharedComponent/ButtonComponent';
export default function App() {
const[text, setText] = useState('');
const[todoList, setToDoList] = useState([]);
return (
<ImageBackground
source={require('./assets/todoimages.png')}
style={{width: '100%', height: '100%'}}
>
<SafeAreaView>
<View style={styles.container}>
<InputComponent onchangeValue={setText}
/>
<ButtonComponent
addItem={setToDoList}
itemToAdd={text}
/>
</View>
<View>
{todoList.length > 0 && todoList.map((value) => <Text>{value}</Text>)}
</View>
</SafeAreaView>
</ImageBackground>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'baseline',
justifyContent: 'center',
paddingBottom:'10%'
},
});
I am getting the error :
Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
can anyone tell me why I am getting the error and what is the solution for that?
below is the button component:
import {View,Button, StyleSheet} from 'react-native';
const ButtonComponent = (props) =>{
return(
<View style={styles.container}>
<View style={styles.buttonContainer}>
<Button
onPress={props.addItem(prevArray=> [...prevArray, props.itemToAdd])}
title="ADD"
/>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
buttonContainer: {
margin: 20
},
})
export default ButtonComponent;
below is the input component:
import { Text, TextInput, View } from 'react-native';
const InputComponent = (props)=>{
return(
<TextInput
style={{height: 40, backgroundColor:'white'}}
placeholder="add the item in to do list"
onChangeText={newText => props.onchangeValue(newText)}
/>
)
}
export default InputComponent;
You must use arrow-functions in the onPress method of your buttonComponent like this:
onPress={()=>props.addItem(...)}

Information not passing into component

In the code sample below, I am trying to show results.length but it does not show. The information is coming from the App.js screen, a filter function which I have pasted below. When I call <ResultsList reults={filtersResultsByPrice('$')} title='Cost Effective'/>, there may not be anything that is actually being sent into the ResultsList.js screen.
Here is the repo:
https://github.com/elaitman1/React-Native-Hooks-Project-1
ResultsList.js:
import React from 'react'
import {Text, View, StyleSheet} from 'react-native'
const ResultsList = ({title, results}) => {
if (results == null){
return null
}else{
return (
<View>
<Text style={styles.title}>{title}</Text>
<Text style={styles.title}>results: {results.length}</Text>
</View>
)
}
}
const styles = StyleSheet.create({
title:{
fontSize: 18,
fontWeight: 'bold'
}
})
export default ResultsList
App.js:
import { StyleSheet, Text, View } from 'react-native';
import SearchBar from './src/Components/SearchBar'
import React, {useState} from 'react'
import useResults from './src/hooks/useResults'
import ResultsList from './src/Components/ResultsList'
export default function App() {
const [term, setTerm] = useState('')
const [searchApi, results, errorMessage] = useResults()
const filtersResultsByPrice = (dollarSign) =>{
return results.filter((result) => {
return result.price === dollarSign
})
}
return (
<View>
<SearchBar
term={term}
onTermChange={setTerm}
onTermSubmit={() => searchApi(term)}
/>
{errorMessage ? <Text>{errorMessage}</Text> : null}
<Text>We have found {results.length} results</Text>
<ResultsList reults={filtersResultsByPrice('$')} title='Cost Effective'/>
<ResultsList reults={filtersResultsByPrice('$$')} title='Bit Pricier'/>
<ResultsList reults={filtersResultsByPrice('$$$')} title='Big Spender'/>
</View>
);
}
const styles = StyleSheet.create({
container: {
borderColor: 'black',
height: 40,
borderWidth: 3,
marginTop: 40
},
});

Is this the correct way to consume an API with React Native, Expo, and Reeact Native Paper?

I am new to React Native and I am trying to create an application with it.
The problem is when I try to display the data in the application.
I am trying to consume a REST API to be able to display the data but it is not showing me anything.
Besides this it does not show me what the error is so I am confused.
I think it's like I'm consuming the API but I can't find the error.
This would be my code:
import { StatusBar } from 'expo-status-bar';
import React, { useEffect, useState, useContext } from 'react';
import { StyleSheet, Text, View, FlatList, Image} from 'react-native';
const MORE_ICON = Platform.OS === 'ios' ? 'dots-horizontal' : 'dots-vertical';
import { Appbar } from 'react-native-paper';
import { Platform } from 'react-native';
import { Searchbar } from 'react-native-paper';
import { Avatar, Button, Card, Title, Paragraph } from 'react-native-paper';
import { render } from 'react-dom';
const API_ENDPOINT = 'https://localhost:5001/api/Medicines/';
export default function App () {
const [searchQuery, setSearchQuery] = React.useState('');
const onChangeSearch = query => setSearchQuery(query);
const [data, setData] = useState([]);
const [error, setError] = useState(null);
useEffect(() => {
fetch(API_ENDPOINT)
.then(response => response.json())
.then(results => {
setData(results);
})
.catch(err => {
setError(err);
});
}, []);
return (
<View >
<Appbar.Header>
<Appbar.Content title=" Medicine" />
</Appbar.Header>
<Searchbar
placeholder="Search"
onChangeText={onChangeSearch}
value={searchQuery}
/>
<FlatList
data={data}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<Card>
<Card.Content>
<Title>{`${item.name.id}`}</Title>
<Paragraph></Paragraph>
</Card.Content>
<Card.Cover />
<Card.Actions>
<Button>info</Button>
</Card.Actions>
</Card>
)}
/>
</View>
)
}
UPDATE
Add two if conditions, each returning a JSX for two different scenarios. First, when the data is fetched, a loading indicator is displayed. Second, when there is an error, an error message is displayed.
But it shows me the scenario of the error "Error fetching data... Check your network connection!"
export default function App() {
// state variables defined
// fetch data using useEffect
if (isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" color="#5500dc" />
</View>
);
}
if (error) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ fontSize: 18}}>
Error fetching data... Check your network connection!
</Text>
</View>
);
}
// ...
}

React Native - React Navigation Cannot use Hooks in DrawerContent

I am developing an e-commerce application using React Native and I am trying to use useState in the drawerContent and it tells me this
Error: Invalid hook call. Hooks can only be called inside of the body
of a function component. This could happen for one of the following
reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
Thank you in advance for your answers.
Here's the code
import React, { useState } from 'react'
import { View, Text, TouchableOpacity, FlatList, StyleSheet, StatusBar } from 'react-native'
import IonIcons from "react-native-vector-icons/Ionicons"
import { categories } from '../../../services/DataTest'
import DrawerSearch from './DrawerSearch'
import DrawerItem from './DrawerItem'
export default function DrawerContent (props) {
const [search, setSearch] = useState("");
return (
<View>
<TouchableOpacity
style={styles.customDrawerTouch}
>
<View style={styles.backButtonRow}>
<IonIcons
name="ios-arrow-back"
size={25}
style={styles.customDrawerIcon}
color="#666666"
/>
<Text style={{ color: '#666666' }}>Back to Components</Text>
</View>
</TouchableOpacity>
<DrawerSearch value={search} setValue={setSearch}/>
<FlatList
data={categories}
keyExtractor={(item, index) => index.toString()}
renderItem={DrawerItem}
/>
</View>
);
}
const styles = StyleSheet.create({
customDrawerTouch: {
marginTop: StatusBar.currentHeight,
paddingLeft: 13,
paddingTop: 15,
},
customDrawerIcon: {
paddingRight: 10
},
backButtonRow: {
flexDirection: 'row',
alignItems: 'center',
paddingBottom: 17,
paddingLeft: 3,
borderBottomColor: '#F0F0F0',
borderBottomWidth: 1,
},
});
I'm using this component here
import * as React from 'react';
import { View, StyleSheet, StatusBar } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import HeaderCategorie from '../../components/categories/index/HeaderCategorie';
import SearchBar from '../../components/home/index/SearchBar';
import DrawerContent from '../../components/categories/index/DrawerContent';
const Drawer = createDrawerNavigator();
function CategoriesScreen({ navigation }) {
return (
<View style={styles.container}>
<HeaderCategorie navigation={navigation}/>
<View style={styles.headerSearch}>
<SearchBar />
</View>
</View>
)
}
export default function Categories() {
return (
<Drawer.Navigator initialRouteName="Categories"
drawerContent={DrawerContent}
screenOptions={{headerShown:false}}
>
<Drawer.Screen name="Categories" component={CategoriesScreen} />
</Drawer.Navigator>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "flex-start",
alignItems: "center",
marginTop: StatusBar.currentHeight,
},
headerSearch: {
marginVertical:10
},
headerSearchText: {
fontWeight:"bold",
fontSize:35,
marginLeft:20,
marginVertical:15,
}
});
Reason: By using drawerContent={DrawerContent}, you are actually passing the reference of the DrawerContent function, which ends up breaking rules of hooks.
So to resolve this, change the following line:
<Drawer.Navigator initialRouteName="Categories"
drawerContent={DrawerContent}
screenOptions={{headerShown:false}}
>
to this
<Drawer.Navigator initialRouteName="Categories"
drawerContent={(props)=> <DrawerContent {...props}/>} // here
screenOptions={{headerShown:false}}
>
demo snack

Accessing navigation parameters Expo-Go

I have got "Screen1" where I create a string "blabla". According to the documentation, I can set it as a navigation parameter:
export default function Screen1() {
const navigation = useNavigation();
navigation.navigate("Screen2", { item: "blalbla" });
return (
<View>
<Text>Render some stuff</Text>
</View>
);
}
On Screen2 I should be able to access it with:
export default function Screen2({ route, navigation }) {
const { item } = route.params;
console.log(item);
return (
<View>
<Text>Render some stuff</Text>
</View>
);
}
Now, this returns:
TypeError: undefined is not an object (evaluating 'route.params.item')]
I also tried some other examples without success.
Referring to React-Native documentation: https://reactnavigation.org/docs/params/
I've created a Snack. Check this out.
Follow below steps to solve your problem
Create a Folder called navigation where your App.js is located.
Then inside this folder create a file called AppNavigator.js
Inside AppNavigator.js paste this
import React from 'react';
import { View } from 'react-native';
import { createStackNavigator } from '#react-navigation/stack';
import Screen1 from '../screens/Screen1';
import Screen2 from '../screens/Screen2';
const Stack = createStackNavigator();
function AppNavigator() {
return (
<Stack.Navigator>
<Stack.Screen name="Screen1" component={Screen1} />
<Stack.Screen name="Screen2" component={Screen2} />
</Stack.Navigator>
);
}
export default AppNavigator;
Now create another folder called screens where your App.js is located
Inside this folder create your two files Screen1.js and Screen2.js
They should look like this
Screen1.js -
import React from 'react';
import { View, StyleSheet, Text, Button } from 'react-native';
function Screen1({ navigation }) {
return (
<View style={styles.container}>
<Text>Screen 1</Text>
<Text onPress={() => navigation.navigate('Screen2', { item: 'blalbla' })}>
Press ME
</Text>
</View>
);
}
export default Screen1;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
Screen2.js -
import React from 'react';
import { View, StyleSheet, Text, Button } from 'react-native';
function Screen2({ route, navigation }) {
const { item } = route.params;
return (
<View style={styles.container}>
<Text>Screen 2</Text>
<Text onPress={() => navigation.navigate('Screen1')}>{item}</Text>
<Text onPress={() => navigation.navigate('Screen1')}>Press ME</Text>
</View>
);
}
export default Screen2;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
Now you should see route parameters inside Screen2
navigation object is probably not present in the screen
change Screen1({ navigation }) to Screen1(props) and do console.log(props) to check if you see a navigation object there

Resources