So I was making this movie browser project in which I had to fetch data from OMDb API(http://www.omdbapi.com/) and display the data in a Flatlist component.
Although I managed to display 10 results of every movie searched for(as API return 10 items on every call), I added a button that would run a function to send a request again to the API using the page parameter, fetch 10 more results and concatenate the results to the movies.
But as soon as I press the button and run the function, this error appears undefined is not an object (evaluating 'item.Title').
This is my code for the Home Component => Home.js
import React, { useState, useEffect } from 'react';
import { StyleSheet, View, Text, FlatList, TouchableHighlight, Image, Button} from 'react-native';
import { TextInput } from 'react-native-gesture-handler';
import { fetchMovies } from "../api/api";
export default class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
text: "",
movies: null,
};
}
//update search text
componentDidUpdate(prevState) {
if (this.state.text !== prevState.text) {
this.getSearch(this.state.text);
}
}
//get search results from fetchMovies
getSearch = async text => {
const results = await fetchMovies(text)
this.setState({ movies: results });
};
////////////////////////////Function making API call using the page parameter///////////
//loading more movies
handleLoadMore = async() => {
try {
const page = Math.trunc(this.state.movies.length / 10) + 1;
const res = await fetchMovies(this.state.text, page);
this.setState(prevState => ({
movies: prevState.movies.concat(res.movies)
}))
}catch(err){
console.log(err.message);
}
}
//////////////////////////////////////////////////////////
//movie title and poster to render in the flatlist
movieCard = ({ item }) => {
return (
<TouchableHighlight
style={styles.movieCard}
underlayColor="white"
onPress={() => {
this.props.navigation.navigate("Details", {
title: item.title,
id: item.imdbID
});
}}
>
<View>
<Image
style={styles.movieImage}
source={ {uri: item.Poster} }
/>
<View style={{alignItems: 'center'}}>
<Text style={styles.movieTitle}>{item.Title} ({item.Year})</Text>
</View>
</View>
</TouchableHighlight>
);
};
render() {
return(
<View style={styles.container}>
<TextInput
style={styles.searchBox}
autoCorrect={false}
autoCapitalize='none'
autoFocus maxLength={45}
placeholder='Search'
onChangeText={(text) => this.setState({ text })}
value={this.state.text}
/>
{this.state.movies ?
<FlatList
style={styles.movieList}
data={this.state.movies}
renderItem={this.movieCard}
keyExtractor={item => item.Title + item.imdbID}
/>
:
<Text
style={{
alignSelf: 'center',
paddingTop: 150,
justifyContent: 'center',
color: '#8a8787',
fontStyle: 'italic' }}>
search for a movie above...
</Text>
}
<Button
onPress={this.handleLoadMore}
title="Load More"
color="#841584"
/>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#DDD',
alignItems: 'center',
},
searchBox: {
fontSize: 20,
fontWeight: '300',
padding: 10,
width: '100%',
backgroundColor: 'white',
borderRadius: 10,
marginBottom: 30
},
movieList: {
flex: 1,
marginHorizontal: 30,
},
movieCard: {
flex: 1,
margin: 5,
padding: 5,
},
movieImage: {
width: '100%',
height: 350,
borderRadius: 10,
alignSelf: 'center',
},
movieTitle: {
marginTop: 10,
fontSize: 20,
color: '#333'
}
});
This is the code for api functions => api.js
const API_KEY = "API_KEY";
//fetch search data from omdb api
export const fetchMovies = async (response, page) => {
const url = `http://www.omdbapi.com/?apikey=${API_KEY}&s=${response}`;
try {
let response = await fetch(url);
if(page) {
response = await fetch(url + `&page=${page}`)
}
const { Search } = await response.json();
return Search;
} catch (err) {
return console.log(err);
}
};
//fetch ID from omdb api
export const fetchById = async id => {
const url = `http://www.omdbapi.com/?apikey=${API_KEY}&i=${id}`;
try {
const response = await fetch(url);
const results = await response.json();
return results;
} catch (err) {
return console.log(err);
}
};
I know solution to this is probably simple but being new to react-native I am not able to figure it out.
regarding FlatList, In docs they apparently pass lambda which returns rendered items to renderItem prop
Also your initialized state.movies is null and i think it should be an empty array
this.state = {
text: "",
movies: [],
};
<FlatList
style={styles.movieList}
data={this.state.movies}
renderItem={({item}) => this.movieCard({item})}
keyExtractor={item => item.Title + item.imdbID}
Related
I'm trying to access some data input on one page by adding it to sqlite database and then displaying it on another page from the created sqlite database.
The value is not being printed, how can I check if the data is being added to the database in the first place?
I am creating a database and a table, and taking an input value on the home page and passing that to the database.
Next, I navigate to another page and display the data that was previously input from the database.
I don't know how many more details I can add.
import React, {useEffect, useState} from 'react';
import {StyleSheet, View, Text, Pressable, Alert} from 'react-native';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import CustomButton from './utils/CustomButton';
import sqlite from 'react-native-sqlite-storage';
import {TextInput} from 'react-native-gesture-handler';
const Stack = createStackNavigator();
const db = sqlite.openDatabase(
{
name: 'MainDB',
location: 'default',
},
() => {},
error => {
console.log(error);
},
);
function ScreenA({navigation}) {
const [info, setInfo] = useState('');
useEffect(() => {
createTable();
getData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const onPressHandler = () => {
navigation.navigate('ScreenB');
};
const createTable = () => {
db.transaction(tx => {
tx.executeSql(
'CREATE TABLE IF NOT EXISTS ' +
'Data ' +
'(ID INTEGER PRIMARY KEY AUTOINCREMENT, Info TEXT);',
);
});
};
const getData = () => {
try {
db.transaction(tx => {
tx.executeSql('SELECT Info FROM Data', [], (_tx, results) => {
var len = results.rows.length;
if (len > 0) {
navigation.navigate('ScreenB');
}
});
});
} catch (error) {
console.log(error);
}
};
const setData = async () => {
if (info.length === 0) {
Alert.alert('warning', 'please enter data');
} else {
try {
await db.transaction(async tx => {
await tx.executeSql('INSERT INTO Data (Info) VALUE (?)', [info]);
});
navigation.navigate('ScreenB');
} catch (error) {
console.log(error);
}
}
};
return (
<View style={styles.body}>
<Text style={styles.text}>hello</Text>
<TextInput
style={styles.input}
placeholer="enter your data"
onChangeText={value => setInfo(value)}
/>
<CustomButton
title="go to data"
color="#1eb900"
onPressFunction={setData}
/>
</View>
);
}
function ScreenB({navigation, route}) {
const [info, setInfo] = useState('');
const onPressHandler = () => {
navigation.navigate('ScreenA');
};
useEffect(() => {
getData();
}, []);
const getData = () => {
try {
db.transaction(tx => {
tx.executeSql('SELECT Info FROM Data'),
[],
(_tx, results) => {
let len = results.rows.length;
if (len > 0) {
let userInfo = results.rows.item(0);
setInfo(userInfo);
}
};
});
} catch (error) {
console.log(error);
}
};
return (
<View style={styles.body}>
{/* <Text style={styles.text}>Screen B</Text> */}
<Text style={styles.text}>Welcome {info} </Text>
<Pressable
onPress={onPressHandler}
style={({pressed}) => ({backgroundColor: pressed ? '#ddd' : '#0f0'})}>
{/* <Text style={styles.text}>Go Back to Screen A</Text> */}
</Pressable>
</View>
);
}
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="ScreenA" component={ScreenA} />
<Stack.Screen name="ScreenB" component={ScreenB} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
body: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
fontSize: 40,
fontWeight: 'bold',
margin: 10,
},
input: {
width: 300,
borderWidth: 1,
borderColor: '#555',
borderRadius: 10,
backgroundColor: '#ffffff',
textAlign: 'center',
fontSize: 20,
marginBottom: 10,
},
});
export default App;
I have a login page. There, the user enters data and submits to the API. The API gives an answer that there is such a user and gives him an id from the database. I write this id in storage.
Next, the user is taken to the home page.
There is a component that is responsible for getting the username (and indeed all other data)
the essence of the component:
1 The parameter receives an id and forms it into a json request.
2 The parameter sends this request to the API and receives the user's data in the response (if the id matches)
3) return which draws the interface and gives the user data from the API response
Problem:
When changing an account (or re-logging in), it gives a json request error (in fact, the API does not accept an empty request, so it rejects it)
The point of getting an ID is 100%. When the application is updated again, the id turns out to be generated in json and after that I already get data about the user.
How to fix it? In fact, it must first receive the id, and only then the id is sent and the data is received, however, at the first entry into the application, he does not want to receive the ID immediately, but only after a reboot (ctlr + s in VS code)
//LOGIN.js
import React, { Component } from 'react';
import { View, Pressable, Text, TextInput, TouchableOpacity } from 'react-native';
import AsyncStorage from '#react-native-async-storage/async-storage';
import styles from './style';
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
email : '',
password : '',
check_textInputChange : false,
secureTextEntry : true,
id : '',
};
}
componentDidMount(){
this._loadInitialState().done();
}
//Сheck that the user with id does not throw out on the authorization screen when exiting the application:
_loadInitialState = async () => {
var id = await AsyncStorage.getItem('id');
if (id !== null) {
this.props.navigation.navigate("HomeScreen")
this.id = id
}
}
InsertRecord () {
var Email = this.state.email;
var Password = this.state.password;
if ((Email.length==0) || (Password.length==0)){
alert("Missing a required field!");
}else{
var APIURL = "http://10.0.2.2:8080/SignIn/login.php";
var headers = {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
};
var Data ={
Email: Email,
Password: Password
};
fetch(APIURL,{
method: 'POST',
headers: headers,
body: JSON.stringify(Data)
})
.then((Response)=>Response.json())
.then((Response)=>{
alert(Response[0].Message)
if (Response[0].Message == "Success") {
console.log(Response[0].Message)
// eslint-disable-next-line react/prop-types
AsyncStorage.setItem('id',Response[0].Id);
this.props.navigation.navigate("HomeScreen");
console.log(Response[0].Id);
}
console.log(Data);
})
.catch((error)=>{
console.error("ERROR FOUND" + error);
})
}
}
updateSecureTextEntry(){
this.setState({
...this.state,
secureTextEntry: !this.state.secureTextEntry
});
}
render() {
return (
<View style={styles.viewStyle}>
<View style={styles.action}>
<TextInput
placeholder="Enter Email"
placeholderTextColor="#ff0000"
style={styles.textInput}
onChangeText={email=>this.setState({email})}
/>
</View>
<View style={styles.action}>
<TextInput
placeholder="Enter Pass"
placeholderTextColor="#ff0000"
style={styles.textInput}
secureTextEntry={this.state.secureTextEntry ? true : false}
onChangeText={password=>this.setState({password})}
/>
<TouchableOpacity
onPress={this.updateSecureTextEntry.bind(this)}>
</TouchableOpacity>
</View>
{/* Button */}
<View style={styles.loginButtonSection}>
<Pressable
style={styles.loginButton}
onPress={()=>{
this.InsertRecord()
}}
>
<Text style={styles.text}>Войти</Text>
</Pressable>
</View>
</View>
);
}
}
//INFOSTATUS.js
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, TouchableOpacity, SafeAreaView, FlatList, StyleSheet, Button, View, Text } from 'react-native';
import { useNavigation } from '#react-navigation/native'
import AsyncStorage from '#react-native-async-storage/async-storage';
function InfoStatus() {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
const [idUser, setIdUser] = useState();
//check ID
const idcheck = async () => {
try {
const get = await AsyncStorage.getItem('id')
setIdUser (get)
} catch(e) {
// read error
}
}
//Sending data to api and getting user data
const getNotifications = async () => {
const send = {
id:idUser
}
try {
const response = await fetch('http://10.0.2.2:8080/InfoStatus/InfoStatus.php', {
method: 'POST',
body: JSON.stringify(send),
headers: {
'Content-Type': 'application/json'
}
});
const data = await response.json();
setData(data);
console.log(data);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
useEffect(() => {
idcheck();
getNotifications();
}, []);
//Initialization of received data
const Item = ({ name, middlename,status,number,city }) => (
<View style={StyleInfo.container}>
<View style={StyleInfo.container2}>
<Text style={StyleInfo.TextStyle}> Dear, </Text>
<Text style={StyleInfo.TextStyleData} key ={name}> {name} {middlename} </Text>
</View>
<View style={StyleInfo.container2}>
<Text style={StyleInfo.TextStyle}> Number: </Text>
<Text style={StyleInfo.TextStyleData}key ={number}> № {number} </Text>
<TouchableOpacity
onPress={() =>
navigation.navigate('InfoParser')
}
>
<Text style={StyleInfo.ButtonAdress}>Find out the address</Text>
</TouchableOpacity>
</View>
<View style={StyleInfo.container2}>
<Text style={StyleInfo.TextStyle}> Status: </Text>
<Text style={StyleInfo.TextStyleData} key ={status}> {status} </Text>
</View>
<View style={StyleInfo.container2}>
<Text style={StyleInfo.TextStyle}> City: </Text>
<Text style={StyleInfo.TextStyleData} key ={city}> {city} </Text>
</View>
<TouchableOpacity
style={StyleInfo.Button}
onPress={() =>
navigation.navigate('InfoParser')
}
>
<Text style={StyleInfo.TextButton}>Get contacts of friends</Text>
</TouchableOpacity>
</View>
);
const renderItem = ({ item }) => (
<Item name={item.name} middlename={item.middlename} status={item.status} yik={item.yik} elections={item.elections} />
);
return (
<SafeAreaView>
{isLoading ? <ActivityIndicator size="large" color="#00ff00"/> : (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
)}
</SafeAreaView>
);
}
const StyleInfo = StyleSheet.create({
container:{
width: 390,
height: 190,
borderWidth: 1,
borderRadius: 2,
marginLeft: 10,
marginBottom: 10,
backgroundColor: '#E9E9E9',
},
container2:{
flexDirection: "row",
},
TextStyle: {
fontFamily: 'Raleway',
fontStyle: 'normal',
fontWeight: 'normal',
fontSize: 18,
marginTop: 5,
marginLeft: 5,
bottom: 10,
top: 10
},
TextStyleData: {
fontSize: 18,
marginTop: 5,
top: 10,
fontWeight: 'bold',
},
ButtonAdress: {
fontSize: 18,
marginTop: 5,
marginLeft: 20,
top: 10,
color: "#ff0000",
},
Button: {
width: 310,
height: 40,
marginTop: 10,
marginLeft: 5,
bottom: 10,
borderWidth: 1,
borderRadius: 2,
top: 10,
alignSelf: 'center',
backgroundColor: "#ff0000",
},
TextButton: {
marginTop: 5,
fontSize: 16,
alignSelf: 'center',
fontWeight: 'bold',
color: 'white',
}
}
)
export {InfoStatus}
PS:
I also caught one thing that when I try to get an id via async / await, then most likely the point is that it does not have time to get the value before rendering. I have run out of ideas, I would like to receive more other suggestions
PSS:
I also know that in fact, even if I passed the value through the navigator, I would pass it to the homescreen. Although my InfoStatus is embedded in the Homescreen and I need to somehow pass this parameter there.
Although in general the question interests me a lot, because I will need this parameter everywhere. Therefore, finding one universal solution would be cool.
I am not 100% sure I understand the question so here a few hints I would give you.
You can pass parameters when navigating like this:
navigation.navigate('somescreen', {
param: 86,
otherParam: 'myBestFriendTheParam',
})
On the next screen you have to then read it from the route.params.
You could use redux to have your user data at hand while the app is open and user logged in? That would give you the data where ever you want basically.
If async/wait does not work why don't you use then-chains like in the rest of your code?
I'm new to react native and I'm not able to consume this api, when I start this app in the browser, it works fine, but when I go to the expo app it doesn't display the pokemon image, could someone help me?
import { StatusBar } from 'expo-status-bar';
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View, Button, Alert, TextInput, Image } from 'react-native';
interface PokeInterface {
sprites : {
back_default : string;
}
}
export default function App() {
const [text, setText] = useState<string>("")
const [response, setResponse] = useState<PokeInterface | any>()
const [image, setImage] = useState<string>()
const handleText = (text : string) => {
setText(text)
}
const searchApi = (pokemonName : string) => {
fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonName}/`, { method: 'GET'})
.then((response) => response.json())
.then((response) => setResponse(response))
}
useEffect(() => {
if(text){
searchApi(text)
}
if(response){
const {sprites} = response
setImage(sprites.front_default)
}
return () => {
if(image){
setImage("")
}
}
},[text, response])
return (
<View style={styles.container}>
<View style={styles.topbar}>
<Text style={styles.title}>Pokedex Mobile</Text>
<TextInput
style={styles.input}
onChangeText={(value: any) => handleText(value)}
value={text}
placeholder="Search Pokemon"
keyboardType="default"
/>
<Text style={styles.text}>{text}</Text>
</View>
{image && (
<Image
style={styles.logo}
source={{uri : `${image}`}}
/>
)}
</View>
);
}
const styles = StyleSheet.create({
text : {
fontSize: 30,
color : "red"
},
input: {
height: 40,
margin: 12,
borderWidth: 1,
padding: 10,
},
container : {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
title: {
fontSize: 30,
color: '#000'
},
topbar: {
},
logo : {
width: 200,
height: 200
}
});
Your current code causes an infinite loop...
You type some text which triggers searchApi(text)
That writes to response which triggers your effect hook
Because text is still truthy, it triggers searchApi(text) again
Goto #2
As far as I can tell, you can simply discard most of response and just retrieve the image when the text changes.
// this doesn't need to be defined in your component
const getPokemonImage = async (name: string) => {
const res = await fetch(
`https://pokeapi.co/api/v2/pokemon/${encodeURIComponent(pokemonName)}/`
);
if (!res.ok) {
throw new Error(`${res.status}: ${await res.text()}`);
}
return (await res.json<PokeInterface>()).sprites.front_default;
};
export default function App() {
const [text, setText] = useState<string>("");
const [image, setImage] = useState<string>(""); // initial value
const handleText = (text: string) => {
setText(text);
};
useEffect(() => {
if (text) {
getPokemonImage(text)
.then(setImage)
.catch(err => {
console.error("getPokemonImage", err)
// show an error message or something
});
}
}, [ text ]); // only run on text change
import React, {useEffect, useState} from 'react';
import {StyleSheet, Text, View, TextInput, Image, Button} from 'react-native';
// Sorry for removing the types i was using JS
// This code works test it for yourself
export default function App() {
const [text, setText] = useState('');
const [response, setResponse] = useState(); // Here use PokeInterface || any as you are doing conditional checking
const [image, setImage] = useState();
const handleText = e => {
setText(e);
};
const searchApi = pokemonName => {
fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonName}/`, {method: 'GET'})
.then(response => response.json())
.then(response => setResponse(response));
};
useEffect(() => {
if (response) {
const {sprites} = response;
console.log(response);
setImage(sprites.front_default);
}
return () => {
if (image) {
setImage('');
}
};
}, [image, text, response]); // you have to pass all the dependencies so useEffect will be invoked as you didnt pass image dep the useeffct was not invoking
return (
<View style={styles.container}>
<View style={styles.topbar}>
<Text style={styles.title}>Pokedex Mobile</Text>
<TextInput
style={styles.input}
onChangeText={(value: any) => handleText(value)}
value={text}
placeholder="Search Pokemon"
keyboardType="default"
/>
<Text style={styles.text}>{text}</Text>
</View>
{image && <Image style={styles.logo} source={{uri: `${image}`}} />}
<Button
title={'Submit'}
onPress={() => searchApi(text)}
disabled={!text}
/>
</View>
);
}
const styles = StyleSheet.create({
text: {
fontSize: 30,
color: 'red',
},
input: {
height: 40,
margin: 12,
borderWidth: 1,
padding: 10,
},
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
title: {
fontSize: 30,
color: '#000',
},
topbar: {},
logo: {
width: 200,
height: 200,
},
});
I am having 2 problems using React Native and Firebase Real Time Database.
When I add something to the list with the text input, all the list itens are duplicated except the item that I just added, this problem is only solved when I refresh the app screen.
When I remove something from firebase dashboard or other client, the list is not updated real time.
import React, {useState, Component} from 'react';
import {
Text,
View,
Switch,
StyleSheet,
FlatList,
TextInput,
Button,
TouchableOpacity,
SafeAreaView,
VirtualizedList,
} from 'react-native';
import database from '#react-native-firebase/database';
class MenuBreakFastScreen extends React.Component {
state = {newItem: ''};
state = {itens: []};
componentDidMount() {
let dbRef = database().ref('/cafe/itens/');
this.listenerFirebase(dbRef);
}
listenerFirebase(dbRef) {
dbRef.on('value', dataSnapshot => {
const newItens = JSON.parse(JSON.stringify(this.state.itens));
dataSnapshot.forEach(child => {
newItens.push({
name: child.val().name,
key: child.key,
});
this.setState({itens:newItens});
});
});
}
addItem() {
if (this.state.newItem === '') {
return;
}
database().ref('/cafe/itens/').push({
name: this.state.newItem,
});
this.setState({
newItem: '',
});
}
render() {
const {itens} = this.state;
const {newItem} = this.state;
const renderItem = ( {item}) => {
return(
<ItemAsset title={item.name}/>
);
}
return (
<SafeAreaView
style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<FlatList
data={itens}
renderItem={renderItem}
keyExtractor={item => item.key}
/>
<SafeAreaView style={{flexDirection: 'row'}}>
<TextInput
style={styles.input}
onChangeText={text =>
this.setState({
newItem: text,
})
}
value={newItem}
/>
<TouchableOpacity style={styles.Botao} onPress={() => this.addItem()}>
<Text style={styles.BotaoTexto}>+</Text>
</TouchableOpacity>
</SafeAreaView>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
texto: {
fontSize: 35,
},
input: {
color: '#000',
fontSize: 22,
borderWidth: 1,
flex: 8,
margin: 10,
},
BotaoTexto: {
color: '#fff',
fontSize: 22,
},
Botao: {
backgroundColor: '#000',
marginTop: 10,
padding: 10,
flex: 1,
alignItems: 'center',
margin: 10,
},
ListaContainer: {
flexDirection: 'row',
backgroundColor: '#000',
flex: 1,
},
item: {
backgroundColor: '#000',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
flexDirection: 'row',
},
title: {
color: '#ffff',
fontSize: 32,
},
});
const ItemAsset = ( {title} ) => {
return(
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
}
export default MenuBreakFastScreen;
When you are listen for real time changes on real-time database it will send all the items with snapshot when any data is changed. That happens because you are listen for whole list, not only for a single item. Therefore you do not need to get the current list from state. You just have to set the state with retrieved data.
listenerFirebase(dbRef) {
dbRef.on('value', dataSnapshot => {
const newItens = []; // This should be initially empty array. That's all.
dataSnapshot.forEach(child => {
newItens.push({
name: child.val().name,
key: child.key,
});
});
this.setState({itens:newItens});
});
}
After correcting this part the error you got when removing data will be also resolved.
Though I am experienced in React I am very new to react-native. I have tried several answers posted in SO for the same issue but none of them helping me fix the issue.
I have App component and the App component calls Account component. The Account component renders input fields but the input fields are not displayed in UI but If I add only Text in App component like <Text>Hello</Text> it is showing in UI but my custom Account component is not showing in the UI. I am not getting an idea what I am doing wrong.
PFB component details
App.js
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Account from './components/Form/components/Account';
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Account />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Account.js
import React, { Component } from "react";
import { StyleSheet, Text, View, Button, TextInput, ScrollView } from 'react-native';
export default class Account extends Component {
constructor(props){
super(props);
this.state = {
cardNo: "",
amount: 0
}
}
handleCardNo = no => {
this.setState({
cardNo: no
});
}
handleAmount = amount => {
this.setState({
amount
});
}
handleSend = event => {
const { cardNo, amount } = this.state;
this.setState({
loading: true
});
const regex = /^[0-9]{1,10}$/;
if(cardNo == null){
}else if (!regex.test(cardNo)){
//card number must be a number
}else if(!regex.test(amount)){
//amount must be a number
}else{
// const obj = {};
// obj.cardNo = cardNo;
// obj.amount = amount;
// const url = "http://localhost:8080/apple"
// axios.post(url, obj)
// .then(response => return response.json())
// .then(data => this.setState({
// success: data,
// error: "",
// loading: false
// }))
// .catch(err => {
// this.setState({
// error: err,
// success: "",
// loading: false
// })
// })
//values are valid
}
}
render(){
const { cardNo, amount } = this.state;
return(
<View>
<TextInput label='Card Number' style={{height: 40, flex:1, borderColor: '#333', borderWidth: 1}} value={cardNo} onChangeText={this.handleCardNo} />
<TextInput label='Amount' style={{height: 40, flex:1, borderColor: '#333', borderWidth: 1}} value={amount} onChangeText={this.handleAmount} />
<Button title='Send' onPress={this.handleSend}/>
</View>
)
}
}
Your code has some styling issues. Try changing you render function with this
render() {
const { cardNo, amount } = this.state
return (
<View style={{ alignSelf: 'stretch' }}>
<TextInput
placeholder="Card Number"
style={{ height: 40, borderColor: '#333', borderWidth: 1 }}
value={cardNo}
onChangeText={this.handleCardNo}
/>
<TextInput
placeholder="Amount"
style={{ height: 40, borderColor: '#333', borderWidth: 1 }}
value={amount}
onChangeText={this.handleAmount}
/>
<Button title="Send" onPress={this.handleSend} />
</View>
)
}