render-error-text-strings-must-be-rendered-within-a-text-component - javascript

Problem: I am displaying all the BOOKS imgs using Flatlist that is stored in a google URL. I am using expo. When I open the application in a browser with expo it works. But when I run it on my phone it shows me an error as given below.
Error: Render Error : Text strings must be rendered within a Component
here is the code:
import React, { Component } from 'react';
import {
Text,
View,
Image,
TextInput,
FlatList,
SectionList,
StyleSheet,
Button,
} from 'react-native';
class App extends React.Component {
constructor() {
super();
this.state = {
bookName: 'javascript',
};
}
componentDidMount() {
this.fetchApi();
}
fetchApi = async () => {
let apiKey = 'AIzaSyDxoyfayTuP-hFon-b-nuzGjPdDAbpIPCY';
const response = await fetch('https://www.googleapis.com/books/v1/volumes?q=' + this.state.bookName + '&key=' + apiKey + '&maxResults=5');
const json = await response.json();
this.setState({ data: json.items });
};
render() {
return (
<View style={styles.container}>
<Text
style={{
fontFamily: 'Arial',
fontSize: 20,
fontWeight: 'bold',
fontStyle: 'underline',
color: 'yellow',
marginTop: -300,
}}>
<Text>Random Users Data</Text>
</Text>
<View
style={{
width: 210,
height: 50,
marginTop: 50,
justifyContent: 'center',
}}>
<TextInput
style={{
width: 210,
height: 45,
fontSize: 18,
borderWidth: 3,
borderRadius: 12,
borderColor: 'royalblue',
textAlign: 'center',
backgroundColor: 'white',
}}
placeholder="Enter book name"
onChangeText={(item) => this.setState.bookName(item)}
/>{' '}
</View>
<View>
<FlatList
data={this.state.data}
keyExtractor={(x, i) => i}
renderItem={({ item }) => (
<View>
<View style={{ marginTop: 200 }}>
<Image
style={{ width: 128, height: 204, margin: 10 }}
source={{ uri: item.volumeInfo.imageLinks.thumbnail }}
/>
</View>
</View>
)}
/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'black',
},
});
export default App;

Remove the {' '}. You probably accidentally added it while working on your project, but React is interpreting it as a space and complaining that text is found outside of a text component.

Related

React Native, content going under navigation header, SafeAreaView not working

As you can see in the image below, I have to give some top margin in order to "not" hide my half of the content under the navigation header, isn't header supposed to be a "safe area" for the below content, to be on the safe side I provided the SafeAreaView but still my content goes under the Header and unfortunately I have to give some hardcoded margin top value to avoid hiding.
The above image is when I comment marginTop.
Above image is when I add marginTop: 70
Code:
NotificationScreen.tsx:
import {
View,
SafeAreaView,
Text,
StatusBar,
} from 'react-native';
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated';
import OrderItem from '../../components/OrderItem';
const NotificationScreen = () => {
const [orders, setOrders] = useState([]);
useEffect(() => {
// calling API...
}, []);
return (
<SafeAreaView style={styles.container}>
<StatusBar backgroundColor="transparent" translucent />
<Text style={{color: 'lightgray', fontSize: 18}}>My Orders: </Text>
<Animated.FlatList
data={orders}
entering={FadeIn}
leaving={FadeOut}
contentContainerStyle={{
alignItems: 'center',
}}
keyExtractor={(_: any, index) => 'key' + index}
renderItem={({item}) => <OrderItem key={item.id} data={item} />}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
marginTop: 70, // if I remove this, the content goes under the header as shown in image.
flex: 1,
padding: 10,
backgroundColor: COLORS.primary,
},
});
export default NotificationScreen;
One more query, why my OrderItem not taking the full width of FlatList (see image, the gray box is not takin the full width...), I have provided width: 100% to my OrderItem container:
OrderItem.tsx:
const OrderItem = ({data}) => {
return (
<View style={styles.container}>
<View style={styles.textBlock}>
<Text style={styles.label}>Strategy: </Text>
<Text style={styles.info}>{data.strategyTitle}</Text>
</View>
// ... same views as shown in image
</View>
);
};
const styles = StyleSheet.create({
container: {
width: '100%',
paddingVertical: 10,
paddingHorizontal: 10,
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: COLORS.lightGray,
borderRadius: 10,
},
textBlock: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
label: {
color: 'grey',
fontSize: 16,
},
info: {
color: 'white',
fontSize: 16,
},
});
export default OrderItem;
The SafeAreaView does not work currently for Android devices. You need to have something like this to avoid this issue:
import { Platform,StatusBar } from "react-native";
const styles = StyleSheet.create({
container: {
paddingTop: Platform.OS == "android" ? StatusBar.currentHeight : 0,
},
});
<SafeAreaView style={styles.container}>
</SafeAreaView>
And for the OrderItem not taking all available width, remove from Animated.FlatList this:
contentContainerStyle={{alignItems: 'center'}}

When i run this Error: TypeError: navigation.getParam is not a function:

i showing some value list description and images on home screen using Flatlist .when i onpress Flatlist item passing image source and id .value passing getparams but error was TypeError: navigation.getParam is not a function.why??. Please solve issue and edit my code . i am a new to react native please solve my issue.
import React from 'react';
import { StyleSheet, Text, View, FlatList, TouchableOpacity, Image } from 'react-native';
import { Card, Rating } from 'react-native-elements'
import { MaterialCommunityIcons } from '#expo/vector-icons';
import { dishesData } from './DishesData';
const MenuDetailScreen = ({ navigation }) => {
const dish = dishesData.find(
(dish) => dish.id === this.navigation.getParam('id')
);
return (
<View style={styles.container}>
<Card>
<Card.Title
style={styles.titleTextStyle}>{dish.title}</Card.Title>
<Image style={{ height: 300, width: 350 }} source={{ uri: dish.imageSource }} />
</Card>
<Card>
<View style={{ flexDirection: "row" }}>
<Text style={styles.commentsTextStyle}>Comments</Text>
<View style={{ flexGrow: 1 }} />
<TouchableOpacity style={{ paddingBottom: 8 }} >
<MaterialCommunityIcons name="pencil-circle" size={40} color="blue" />
</TouchableOpacity>
</View>
<FlatList
scrollEnabled={false}
data={dish.dishDetails}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => {
return (
<View>
<Text style={styles.headerTextStyle}>{item.comment}</Text>
<Rating
readonly
imageSize={20}
startingValue={item.rating}
style={styles.ratingStyle}
/>
<Text style={styles.spacing}>- {item.author} , {item.created_by}</Text>
</View>
);
}}
/>
</Card>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
paddingBottom: 10
},
commentsTextStyle: {
fontSize: 20,
fontWeight: 'bold',
textAlign: 'left'
},
textInputStyle: {
width: "80%",
padding: 8,
marginBottom: 8,
fontSize: 16
},
submitButtonStyle: {
alignItems: 'center',
width: "80%",
borderRadius: 5,
marginBottom: 8,
padding: 8,
fontWeight: 'bold',
backgroundColor: 'rgba(0, 0, 255, 0.6)',
color: 'black'
},
cancelButtonStyle: {
alignItems: 'center',
width: "80%",
borderRadius: 5,
marginBottom: 8,
padding: 8,
fontWeight: 'bold',
backgroundColor: 'grey',
color: 'black'
},
ratingStyle: {
alignItems: 'flex-start',
paddingBottom: 8
},
titleTextStyle: {
fontSize: 20,
textAlign: 'left'
},
textStyle: {
paddingBottom: 8
},
headerTextStyle: {
fontSize: 16,
fontWeight: 'bold',
paddingTop: 8
},
spacing: {
padding: 8
},
ratingStyle: {
alignItems: 'flex-start',
paddingTop: 8
}
});
export default MenuDetailScreen;
Error place
7 | const MenuDetailScreen = ({ navigation }) =>{
8 |
9 | const dish = dishesData.find(
> 10 | (dish) => dish.id === this.navigation.getParam('id')
11 |
12 | );
13 |
enter code here
Better way is to useNavigation and useRoute from React Navigation.
Step-by-step changes
Step 1
import { useNavigation, useRoute } from '#react-navigation/native';
Step 2
const navigation = useNavigation();
const route = useRoute();
Step 3
const { id } = route.params
Step 4 - Check if you are passing params when you navigate
Example)
onPress={() => navigation.navigate('SCREEN_NAME_HERE', {
PARAM_KEY: PARAM_VALUE
})}
Full Example
import React from 'react';
...
import { useNavigation, useRoute } from '#react-navigation/native';
/*
Navigate to this screen by
navigation.navigate('MenuDetailScreen', {
id: <ID_VALUE_HERE>
})
*/
const MenuDetailScreen = () => {
const navigation = useNavigation();
const route = useRoute();
const { id } = route.params
const dish = dishesData.find(
(dish) => dish.id === id
);
return (
...
)
}
Once you get it working, I recommend you to go over Type checking
with TypeScript for safely navigating between screens in React.
Update the MenuDetailScreen >>
const dish = dishesData.find(
(dish) => dish.id === this.navigation.getParam('id')
);

I cant change the value with setState in React Native

I'm learning react native and I've been trying to solve this issue for last 3 days.
I'm using EXPO, The buttons does not change the value in const [isStarted, setIsStarted] = useState(false)
The buttons titles are: "pause" and "start"
Here is my code:
import React, { useState,useEffect } from 'react';
import { View, StyleSheet, Text, Button,Alert } from 'react-native';
import { colors } from '../../utils/colors';
import { spacing } from '../../utils/sizes';
import { Countdown } from '../../components/Countdown';
import { RoundedButton } from '../../components/RoundedButton';
import {ProgressBar} from 'react-native-paper';
export const Timer = ({ focusSubject }) => {
const [isStarted, setIsStarted] = useState(false);
return (
<View style={styles.container}>
<View style={styles.countdown}>
<Countdown isPaused={!isStarted}/>
</View>
<View styles={{ paddingTop: spacing.xxl }}>
<Text style={styles.title}> Focusing on: </Text>
<Text style={styles.task}> {focusSubject} </Text>
</View>
<View style= {styles.buttonWrapper}>
{isStarted ? (
**<RoundedButton title="pause" onPress={() => setIsStarted(false)} />**
) : (
**<RoundedButton title="start" onPress={() => setIsStarted(true)} />**
)}
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
title: {
color: colors.white,
textAlign: 'center',
},
task: {
color: colors.white,
textAlign: 'center',
fontWeight: 'bold',
},
countdown: {
flex: 0.5,
alignItems: 'center',
justifyContent: 'center',
},
buttonWrapper: {
alignItems: 'center',
flex: 0.3,
padding: 15,
justifyContent: 'center',
},
});
You need to pass a prop name to RoundedButton component and inside of that you need to call onPress
for ex:
import React, { useState,useEffect } from 'react';
import { View, StyleSheet, Text, Button,Alert } from 'react-native';
import { colors } from '../../utils/colors';
import { spacing } from '../../utils/sizes';
import { Countdown } from '../../components/Countdown';
import { RoundedButton } from '../../components/RoundedButton';
import {ProgressBar} from 'react-native-paper';
export const Timer = ({ focusSubject }) => {
const [isStarted, setIsStarted] = useState(false);
const onButtonPress = () => {
setIsStarted(!isStarted)
}
return (
<View style={styles.container}>
<View style={styles.countdown}>
<Countdown isPaused={!isStarted}/>
</View>
<View styles={{ paddingTop: spacing.xxl }}>
<Text style={styles.title}> Focusing on: </Text>
<Text style={styles.task}> {focusSubject} </Text>
</View>
<View style= {styles.buttonWrapper}>
<RoundedButton title={isStarted ? "pause" : "start"} onButtonHandler={onButtonPress} />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
title: {
color: colors.white,
textAlign: 'center',
},
task: {
color: colors.white,
textAlign: 'center',
fontWeight: 'bold',
},
countdown: {
flex: 0.5,
alignItems: 'center',
justifyContent: 'center',
},
buttonWrapper: {
alignItems: 'center',
flex: 0.3,
padding: 15,
justifyContent: 'center',
},
});
Here I added a button handler as a prop into RoundedButton, now inside RoundedButton call onPress={onButtonHandler} in the touchable event.
If you are still facing trouble please share update RoundedButton component code

React native multi select and delete items from state array

I have stored the value locally using array, And I want to delete a single item by using Trash icon. But I need to delete the multi selected items from the array.
So I placed the button "Delete selected". But I am not able to select multiple items and I don't know how to write the functionality to delete multiple items. I'm new for the React Native so kindly help.
Here is my code
import React, { Component } from "react"
import { View, Text, TouchableOpacity, TouchableHighlight, TextInput, StyleSheet, FlatList,onRemove } from 'react-native'
import {Card,CardItem,Right} from 'native-base';
import Swipeout from 'react-native-swipeout'
import Icon from 'react-native-vector-icons/FontAwesome';
import MultiSelect from 'react-native-multiple-select';
class Screen3 extends Component{
constructor(props) {
super(props);
this.state = {
loading: false,
firstname:[],
onPress:true,
unique1:[],
unique:[],
selectedItems : [],
renderData:item,
key1:0
};
}
componentDidMount=()=>{
const{navigation}=this.props
const data=navigation.getParam('data','')
const unique=data.filter((value,index,self)=>self.indexOf(value)===index)
var key=0
const unique1=[]
for(var i=0;i<unique.length;i++){
key=key+1
var result={"name":unique[i],"key":key}
this.state.unique1.push(result)
this.state.key1=this.state.key1+1
this.setState({key1:this.state.key1})
}
}
onPressHandler(item) {
let renderData=[...this.state.renderData];
for(let data of renderData){
if(data.item==item){
data.selected=(data.selected==null)?true:!data.selected;
break;
}
}
this.setState({renderData});
}
deleteItem = (item,index) => {
console.log(item.name,index)
this.state.unique=this.state.unique1
let filtered=this.state.unique.filter((item1) => item1.key !== item.key)
console.log(filtered)
this.setState({unique1:filtered})
}
render(){
return (
<View>
<Text style={styles.heading}>
Manage Screen
</Text>
<TouchableOpacity style = {styles.Button}
onPress={()=>this.deleteItem(item,index) } >
<Text style={styles.button}>Delete selected</Text>
</TouchableOpacity>
<FlatList
data={this.state.unique1}
showsVerticalScrollIndicator={false}
extraData={this.state.key1}
style={{ marginTop: 16 }}
renderItem={({ item, index }) => (
// <TouchableOpacity onPress={() => this.handleData(item)}>
<TouchableOpacity onPress={() => this.onPressHandler(item,index)}>
item!=null?
<Card
style={{
elevation: 10,
marginBottom: 15,
}}
>
<View style={{ flex: 1 }}></View>
<CardItem bordered >
style={
item.selected==true
? {
padding: 10,
borderRadius: 5,
backgroundColor: '#000000',
}
: {
borderRadius: 5,
backgroundColor: '#a1a1a1',
}}
<Text>{item.name}</Text>
<Right style={{alignSelf:'flex-end' } }>
<TouchableOpacity onPress={() => this.deleteItem(item,index)}>
<Icon size={25} name={Platform.OS ==='android' ? "trash" : "ios-trash"} color="red"/>
</TouchableOpacity>
</Right>
</CardItem>
</Card>:null
// </TouchableOpacity>
)
}
/>
</View>
)
}
}
export default Screen3
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
heading: {
fontSize: 23,
paddingVertical:80,
textAlign: 'center',
marginBottom: 30,
marginTop: -40,
},
button:{
width:('39%'),
height:('4%'),
alignItems:'center',
borderWidth:1,
borderRadius:2,
marginTop:-80,
marginHorizontal:10,
marginLeft:110,
justifyContent:'center',
backgroundColor: '#b0c4de',
padding: 9,
fontSize: 15,
margin: 15,
height: 40,
width: 160,
alignItems: 'center'
}
}
)
You would need a different function to delete multiple items and that function would call your deleteItem() function. A simple, but not so efficient way would be to loop through your selectedItems and find them in your data array and then remove each selected item with deleteItem(). You can then improve from there if it's not efficient enough.

Can't Re-render FlatList after deleting last item Although use extraData - React Native

I'm tried to re-render Flat list but can't be updated anymore,
I'm getting the data from real-time DB and passed to Flatlist as a data props,
and write a function to delete an item from the list and DB and work very well, but when I delete the last one of the list I can not see Empty screen "List" just stock with the last one I've deleted Although it's deleted in DB!
code
import React, { Component } from 'react';
import { View, Text, StyleSheet, FlatList, ScrollView, TouchableOpacity } from 'react-native';
import firebase from "react-native-firebase";
import Icon from 'react-native-vector-icons/Ionicons';
class UserFavorites extends Component {
constructor(props) {
super(props);
this.state = {
currentUser: null,
favorites: [],
}
}
componentDidMount() {
const currentUser = firebase.auth().currentUser.uid;
this.setState({ currentUser });
const favorites = firebase.database().ref(`favorites/${currentUser}`);
favorites.on("value", (snapshot) => {
let favorites = []
snapshot.forEach((childSnapshot) => {
favorites.push({
ProviderId: childSnapshot.val().ProviderId,
providerName: childSnapshot.val().providerName,
providerService: childSnapshot.val().providerService,
});
this.setState({ favorites })
});
});
}
_listEmptyComponent = () => {
return (
<View style={styles.container}>
<Text style={{ alignSelf: "center" }}> No favorites Provider Found :O</Text>
</View>
)
}
render() {
const { fav } = this.state;
return (
<View style={styles.container} >
<FlatList data={this.state.favorites}
key={Math.random() * 1000}
contentContainerStyle={{ flexGrow: 1 }}
ListEmptyComponent={this._listEmptyComponent()}
extraData={this.state}
renderItem={({ item }) => {
return (
<ScrollView>
<TouchableOpacity>
<View
style={{
flex: 1,
paddingLeft: 15,
paddingRight: 10,
height: 105,
alignItems: "center",
backgroundColor: "#fafafa",
flexDirection: "row",
borderBottomWidth: .8,
borderBottomColor: "#aaa"
}}>
<Icon style={{ alignSelf: "center" }} name="ios-contact" size={60} color="#1567d3" />
<View style={{ flex: 1, padding: 5, flexDirection: "row" }}>
<View style={{ marginLeft: 27 }}>
<Text style={{
fontSize: 18,
fontWeight: "800",
fontFamily: 'Gill Sans',
color: '#000',
}}>
{item.providerName}
</Text>
<Text style={{
fontSize: 18,
fontWeight: "800",
fontFamily: 'Gill Sans',
color: '#000',
}}>
{item.providerService}
</Text>
</View>
<View style={{ alignItems: "flex-end", justifyContent: "center", flex: 1 }}>
<Icon style={{ marginRight: 20 }}
name={`ios-heart${fav ? "" : "-empty"}`}
size={35} color="#f00"
onPress={() => {
const currentUser = firebase.auth().currentUser.uid;
firebase.database().ref(`favorites/${currentUser}/${item.ProviderId}`).remove().then(() => alert("Removed"))
}}
/>
</View>
</View>
</View>
</TouchableOpacity>
</ScrollView>
)
}
}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default UserFavorites;
You are removing the item from firebase but not from the flatlist's data source this.state.favorites, add a function that'll you call after removing the item from firebase.
_onRemove = (_item) => {
this.setState({
favorites: this.state.favorites.filter(item => item.ProviderId !== _item.ProviderId)
});
}
Pass the item you want to delete to the function in your flatlist
renderItem={({ item }) => {
return ....
//scrollview code
<Icon style={{ marginRight: 20 }}
name={`ios-heart${fav ? "" : "-empty"}`}
size={35} color="#f00"
onPress={() => {
const currentUser = firebase.auth().currentUser.uid;
....
// firebase code
this._onRemove(item);
}
/>
....
//rest of the code
}}

Categories