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
},
});
Related
I'm having an issue about reading my state from another component. I use Redux Toolkit to store my state.
colorPick.js :
import { createSlice } from '#reduxjs/toolkit'
export const colorizerSlice = createSlice({
name: 'colorizer',
initialState: {
color: { nav: '#cecece',
bg: '#ebebeb' }
},
reducers: {
yellow: state => {
state.color = { nav: '#e1ce00',
bg: '#ffed27' }
},
red: state => {
state.color = { nav: '#e11300',
bg: '#ff3d27' }
},
green: state => {
state.color = { nav: '#00e104',
bg: '#4bff27' }
},
pink: state => {
state.color = { nav: '#e100ce',
bg: '#ff27fb' }
},
orange: state => {
state.color = { nav: '#e18b00',
bg: '#ff8527' }
},
// incrementByAmount: (state, action) => {
// state.value += action.payload
// }
}
})
// Action creators are generated for each case reducer function
export const { yellow,
red,
green,
pink,
orange, } = colorizerSlice.actions
export default colorizerSlice.reducer
store.js :
import { configureStore } from '#reduxjs/toolkit'
import colorizerReducer from './reducers/colorPick'
export default configureStore({
reducer: {
colorizer: colorizerReducer,
}
})
App.js :
import { StatusBar } from 'expo-status-bar';
import { useState, useEffect } from 'react';
import { Button, StyleSheet, Text, TextInput, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { Provider } from 'react-redux';
import Notes from './screens/Notes';
import ViewNote from './screens/ViewNote';
import EditNote from './screens/EditNote';
import AddNote from './screens/AddNote';
import store from './redux/store';
export default function App() {
const Stack = createNativeStackNavigator();
return (
<Provider store={store}>
<NavigationContainer>
<Stack.Navigator screenOptions={defaultOptions}>
<Stack.Screen name='Notes' component={Notes} options={notesOptions} />
<Stack.Screen name='ViewNote' component={ViewNote} options={viewNotesOptions} />
<Stack.Screen name='EditNote' component={EditNote} options={editNotesOptions} />
<Stack.Screen name='AddNote' component={AddNote} options={addNotesOptions} />
</Stack.Navigator>
</NavigationContainer>
</Provider>
);
}
ColorPalette.js : (I can read my state in this component)
import { StyleSheet, Text, View, Pressable } from 'react-native'
import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { green, red, yellow, orange, pink } from '../redux/reducers/colorPick'
const ColorPalette = () => {
const { color } = useSelector((state) => state.colorizer);
const dispatch = useDispatch();
console.log(color.nav);
return (
<View style={styles.paletteContainer}>
<Pressable style={[styles.color, {backgroundColor: '#ffed27'}]} android_ripple={{color: '#d9d9d9'}} onPress={() => dispatch(yellow())} />
<Pressable style={[styles.color, {backgroundColor: '#ff3d27'}]} android_ripple={{color: '#d9d9d9'}} onPress={() => dispatch(red())} />
<Pressable style={[styles.color, {backgroundColor: '#4bff27'}]} android_ripple={{color: '#d9d9d9'}} onPress={() => dispatch(green())} />
<Pressable style={[styles.color, {backgroundColor: '#ff27fb'}]} android_ripple={{color: '#d9d9d9'}} onPress={() => dispatch(pink())} />
<Pressable style={[styles.color, {backgroundColor: '#ff8527'}]} android_ripple={{color: '#d9d9d9'}} onPress={() => dispatch(orange())} />
<View style={{backgroundColor: color.nav, width:20}}></View>
<View style={{backgroundColor: color.bg, width:20}}></View>
</View>
)
}
NoteTile.js : (I cannot read in this component)
import { StyleSheet, Text, View, Pressable } from 'react-native'
import React from 'react'
import { useSelector } from 'react-redux'
const NoteTile = ({title, det, pressFunc}) => {
const { color } = useSelector((state) => state.colorizer);
// const color = useSelector((state) => state.colorizer.color);
return (
<View style={styles.tileContainer} >
<Pressable android_ripple={{color: '#cccccc'}}
style={styles.button}
onPress={pressFunc} >
<View style={[styles.innerContainer]} >
<Text style={styles.title} >{title}</Text>
<Text style={styles.details} >{det}</Text>
</View>
</Pressable>
</View>
)
}
export default NoteTile
const styles = StyleSheet.create({
tileContainer: {
flex: 1,
margin: 10,
height: 100,
maxHeight: 400,
borderRadius: 30,
elevation: 5,
overflow: 'hidden',
// backgroundColor: '#ffffff'
backgroundColor: color.bg,
}})
The error that I got is 'Can't find variable: color'
I wrapped my code with Provider.
And I use NoteTile.js in Notes Screen which is within the Provider.
try using it this way
<View style={[styles.tileContainer,{ backgroundColor:color.bg }]} >
I m trying to fetch list of artist from asyncStorage and assign that artist to state name "getArtist" (result is in string so i need to parse to convert into array, it look something like this ["abc", "xyz" , "uvw"]). After that i m mapping it and passing id to AlbumList.js. In AlbumList i m calling a redux-action "searchArtistAlbum(id)" passing id in it and getting list of all albums of that artist, but as i have console.log("showSearchData ===", showSearchData) for artist name, there are 3 artist so it should be called 3 times i.e artist1, artist2, artist3 but its been called like 1.call artist1, artist1, artist1 , 2.call artist2, artist2, artist2 and 3.call artist3, artist3, artist3 and atlast values are same i.e artist3, artist3, artist3. and if i try to pass "showSearchData" as variable in useEffect([showSearchData]) it go into infinite loop.
Home.js
import React, {useEffect, useState} from 'react';
import {View, Text, ScrollView, AsyncStorage} from 'react-native';
import {connect} from 'react-redux';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import Label from '../components/Label';
import HomeHeader from '../components/HomeHeader';
import AlbumList from '../components/AlbumList';
export const Home = ({ navigation, mainNavigation}) => {
const [getArtist, setGetArtist] = useState([])
useEffect(() => {
getTokenResult()
},[])
const getTokenResult = async () => {
let getResult = await AsyncStorage.getItem('access_token')
let getCat = await AsyncStorage.getItem('categories')
let getArt = await AsyncStorage.getItem('artists')
setGetArtist(JSON.parse(getArt))
console.log("getResult ", getResult)
console.log("getArt ", typeof JSON.parse(getArt), JSON.parse(getArt))
console.log("getCat ", getCat)
if (!getResult || !getResult == undefined && !getResult == null){
mainNavigation.navigate('Login')
} else if(!getArt || !getArt === undefined && !getArt == null){
mainNavigation.navigate('Artist')
} else if(!getCat || !getCat === undefined && !getCat == null){
mainNavigation.navigate('Category')
}
}
return (
<ScrollView
style={{flex: 1, backgroundColor: 'rgb(30,30,30)', padding: 15}}>
<HomeHeader />
<View
style={{
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between',
}}>
</View>
{
getArtist && getArtist !== undefined && getArtist.length > 0 ?
getArtist?.map((item, index) => {
return (
<AlbumList id={item && item !== undefined ? item : ""} key={index} />
)
})
:
null
}
</ScrollView>
);
};
const mapStateToProps = state => ({
getToken: state.getToken,
});
const mapDispatchToProps = {};
export default connect(mapStateToProps, mapDispatchToProps)(Home);
AlbumList.js
import React, {useEffect} from 'react';
import {
View,
Text,
StyleSheet,
ScrollView,
ScrollViewComponent,
} from 'react-native';
import {searchArtistAlbum} from '../redux/actions/searchAction';
import AlbumCard from './AlbumCard';
import {connect} from 'react-redux';
function AlbumList({id, searchArtistAlbum, showSearchData}) {
const arr = [1, 2, 3, 4, 5];
useEffect(() => {
searchArtistAlbum(id);
}, []);
console.log('showSearchData === ',showSearchData && showSearchData !== undefined && showSearchData?.items && showSearchData?.items[0]?.artists[0]?.name);
return (
<View style={styles.contView}>
<Text style={styles.textView}>{showSearchData && showSearchData !== undefined && showSearchData?.items !== undefined ? showSearchData?.items[0]?.artists[0]?.name : ""}</Text>
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>
{showSearchData && showSearchData !== undefined
? showSearchData?.items?.map((item, index) => {
return <AlbumCard image={item && item !== undefined ? item?.images[1]?.url : ""} key={index} />;
})
: null}
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
textView: {
color: '#fff',
fontSize: 23,
fontWeight: '700',
},
contView: {
paddingTop: 20,
width: '100%',
},
});
const mapStateToProps = state => ({
showSearchData: state.showSearchData,
});
const mapDispatchToProps = {searchArtistAlbum};
export default connect(mapStateToProps, mapDispatchToProps)(AlbumList);
AlbumCard.js
import React from 'react';
import {View, Text, StyleSheet, Image} from 'react-native';
function AlbumCard({image}) {
return (
<View style={styles.contView}>
<Image
style={styles.img}
source={{
uri:image && image !== undefined ? image : 'https://images4.alphacoders.com/476/thumb-350-47698.png',
}}
/>
<View style={styles.textView}>
<Text style={styles.textView1}>AlbumCard</Text>
<Text style={styles.textView2}>Beast Playlist</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
img: {
width: 150,
height: 150,
},
contView:{
paddingVertical: 20,
marginRight: 20,
},
textView:{
marginVertical: 10
},
textView1:{
fontSize:14,
fontWeight: '700',
color:'#fff'
},
textView2:{
fontSize:14,
color:'rgb(150,150,150)',
paddingVertical: 3,
}
});
export default AlbumCard;
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
So I have a an image selector that when I press, it launches the phone image library and then when I select the image it is supposed to fill that image selector but every time i select an image, I get this error
[TypeError: undefined is not an object (evaluating 'iter[Symbol.iterator]')]
This is how my code looks like this is the App file
import React, {useState} from 'react'
import { Button, StyleSheet, Text, View } from 'react-native'
import Screen from './app/components/Screen'
import ImageInputList from './app/components/ImageInputList'
export default function App() {
const [imageUris, setImageUris] = useState();
const handleAdd = (uri) => {
setImageUris([...imageUris, uri])
}
const handleRemove = uri => {
setImageUris(imageUris.filter(imageUri => imageUri !== uri))
}
return (
<Screen>
<ImageInputList imageUris={imageUris} onAddImage={handleAdd} onRemoveImage={handleRemove} />
</Screen>
)
}
And then this is my 2nd component the "imageInputList"
import React from 'react'
import { StyleSheet, Text, View } from 'react-native'
import ImageInput from './ImageInput'
export default function ImageInputList({imageUris = [], onRemoveImage, onAddImage}) {
return (
<View style={styles.container}>
{imageUris.map((uri) => (
<View key={uri} style={{marginRight: 10}}>
<ImageInput
imageUri={uri}
onChangeImage={() => onRemoveImage(uri)}
/>
</View>
))}
<ImageInput onChangeImage={(uri) => onAddImage(uri)} />
</View>
)
}
And lastly, this is the imageInput component
import React, {useEffect} from 'react'
import { Image, StyleSheet, TouchableWithoutFeedback, Alert, View } from 'react-native'
import {MaterialCommunityIcons} from "#expo/vector-icons"
import * as ImagePicker from "expo-image-picker"
export default function ImageInput({imageUri, onChangeImage}) {
useEffect(() => {
requestPermission();
}, [])
const requestPermission = async () => {
const {granted} = await ImagePicker.requestMediaLibraryPermissionsAsync();
if(!granted) alert("Allow this app to access your image library")
}
const handlePress = () => {
if(!imageUri) selectImage();
else Alert.alert("Delete",
"Are you sure you want to delete this image?",
[{text: "Yes", onPress: onChangeImage(null)}, {text: "No"},])
};
const selectImage = async () => {
try {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
quality: 0.5,
});
if(!result.cancelled) onChangeImage(result.uri);
}
catch (error) {
console.log("Something went wrong in your code", error)
}
}
return (
<TouchableWithoutFeedback onPress={handlePress}>
<View style={styles.container} >
{!imageUri && <MaterialCommunityIcons name="camera" size={40} color="grey" />}
{imageUri && <Image source={{uri: imageUri}} style={styles.image} />}
</View>
</TouchableWithoutFeedback>
)
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#f1f1f1",
borderRadius: 15,
marginTop: 40,
alignItems: 'center',
justifyContent: 'center',
overflow: "hidden",
width: 100,
height: 100,
},
image: {
height: "100%",
width: "100%",
}
})
I know the issue has something to do with "handleAdd" or the "onChangeImage" part but I do not know exactly how to fix them. Thanks in Advance.
The problem is here:
const [imageUris, setImageUris] = useState();
You're trying to spread imageUris but it is not an array when it is first initialized.
Simply replace useState(); with useState([]);
I have a component which I'm trying to connect with the global redux store. But when I do, I got an error which says that "Could not find "store" in the context of "Connect(App)"".
Here is my code:
App.js
import React from 'react';
import { StyleSheet, Text, View, TextInput, Button } from 'react-native';
import {connect} from 'react-redux'
function App() {
const geo = navigator.geolocation
if(!geo) {
} else {
geo.getCurrentPosition((response)=>{console.log(response)}, (response) => {console.log(response)})
}
return (
<View style={{padding: 40}}>
<View style={styles.form}>
<TextInput placeholder="Example text" style={styles.cityInput}/>
<Button title="Press ME!" onPress={(e)=> {console.log(e)}}/>
</View>
</View>
);
}
const styles = StyleSheet.create({
form: {
flexDirection: 'row',
justifyContent: 'space-between',
maxWidth: '100%'
},
cityInput: {
borderColor: 'black',
borderWidth: 2,
borderRadius: 5,
padding: 5,
width: '80%'
}
});
export default connect()(App)
index.js
import React from 'react'
import {AppRegistry} from 'react-native';
import App from './App'
import { name as appName } from './app.json'
import {Provider} from 'react-redux'
import configureStore from './src/reducers/store'
const store = configureStore();
const SunApp = () =>
<Provider store={store}>
<App />
</Provider>
AppRegistry.registerComponent(appName, () => SunApp)
store.js
import positionReducer from './positionReducer';
import sunReducer from './sunReducer';
import cityReducer from './cityReducer';
import {createStore, combineReducers} from 'redux';
const reducers = combineReducers({
positionReducer,
sunReducer,
cityReducer,
})
const configureStore = () => createStore(
reducers,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
export default configureStore;
Here's the error
I can't figure out what I have to do to get rid of this error, so any feedback will be much appreciated
That error seems to come from your react native web entry point where the App is not wrapped in a <Provider (visible in the error message of the screenshot), not from the entry point you shared here.
So, indeed, the problem was in the entry point of my App. Because I was using managed workflow, the entry point of my application was registered to the App component, and my index.js file didn't make anything. So I managed to change my project structure a little bit so now my files looks like this:
App.js
import React from 'react';
import Main from './src/components/Main'
import {Provider} from 'react-redux'
import configureStore from './src/reducers/store'
const store = configureStore();
function App() {
return (
<Provider store={store}>
<Main />
</Provider>
);
}
export default App
Main.js
import React from 'react';
import { StyleSheet, Text, View, TextInput, Button } from 'react-native';
import {useEffect} from 'react'
import {connect, useSelector, useDispatch} from 'react-redux'
import axios from 'axios'
import {setPosition, setSun, setCity, setUndef, setInput} from '../actions'
function Main() {
const position = useSelector(state => state.positionReducer)
const sun = useSelector(state => state.sunReducer)
const city = useSelector(state => state.cityReducer)
const input = useSelector(state => state.inputReducer)
const dispatch = useDispatch();
function fail(error) {
alert(`Currently we can't get your location because: "${error.message}"`)
}
function success(response) {
dispatch(setPosition(response.coords));
}
function findCity(e) {
e.preventDefault()
dispatch(setCity(input))
axios.get('https://api.openweathermap.org/geo/1.0/direct', {
params: {
q: input,
limit: 1,
appid: 'a913b85241698a00b1014abe62a5ca0e'
}
})
.then(response => {
console.log(response);
if(response.data[0]) {
dispatch(setPosition(response.data[0]))
} else {
dispatch(setUndef())
}
})
}
useEffect(() => {
const geo = navigator.geolocation;
if(!geo) {
fail()
} else {
geo.getCurrentPosition(success, fail)
}
// eslint-disable-next-line
},[])
useEffect(() => {
if(position.lat && position.lat !== 'Not Found') {
axios.get('https://api.openweathermap.org/data/2.5/weather', {
params: {
lat: position.lat,
lon: position.lon,
appid: 'a913b85241698a00b1014abe62a5ca0e'
}
})
.then((response) => {
const sunriseTime = new Date(response.data.sys.sunrise * 1000)
const sunsetTime = new Date(response.data.sys.sunset * 1000)
const sun = {
sunrise: `${sunriseTime.getHours()}:${sunriseTime.getMinutes()}`,
sunset: `${sunsetTime.getHours()}:${sunsetTime.getMinutes()}`
}
dispatch(setSun(sun))
})
axios.get('https://api.openweathermap.org/geo/1.0/reverse', {
params: {
lat: position.lat,
lon: position.lon,
limit: 1,
appid: 'a913b85241698a00b1014abe62a5ca0e'
}
})
.then((response) => {
dispatch(setCity(response.data[0].name))
})
}
// eslint-disable-next-line
},[position])
return (
<View style={{padding: 40}}>
<View style={styles.form}>
<TextInput
placeholder="Example text"
style={styles.cityInput}
onChangeText={(e) => {dispatch(setInput(e))}}
onSubmitEditing={(e) => {dispatch(setInput(e.nativeEvent.text)); findCity(e)}}
/>
<Button title="Press ME!" onPress={findCity}/>
</View>
<View style={styles.info}>
<Text style={styles.infoText}>City: {city}</Text>
<Text style={styles.infoText}>Longitude :{position.lon}</Text>
<Text style={styles.infoText}>Latitude: {position.lat}</Text>
<Text style={styles.infoText}>Sunrise time: {sun.sunrise}</Text>
<Text style={styles.infoText}>Sunset time: {sun.sunset}</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
form: {
flexDirection: 'row',
justifyContent: 'space-between',
maxWidth: '100%'
},
cityInput: {
borderColor: 'black',
borderWidth: 2,
borderRadius: 5,
padding: 5,
width: '80%'
},
info: {
marginTop: 0,
marginBottom: 0,
marginLeft: 'auto',
marginRight: 'auto',
width: 'max-content'
},
infoText: {
fontSize: 20,
fontWeight: 700
}
});
export default connect()(Main)