How to get data from Api in TextInput use on React Native? - javascript

I have some issues with TextInput when getting the data from API when calling the function I'm declaring it to fetch the API and get the data Depending on the input
I have a warning like
can't find variable searchInput
and I'm defining the search input in the state and put them to the value of the input, I think the code is right or what?
Code
import React, { Component } from "react";
import {
StyleSheet,
Text,
View,
TextInput,
LinearGradient,
ActivityIndicator,
TouchableOpacity
} from "react-native";
import Icon from "react-native-vector-icons/Ionicons";
export default class Search extends Component {
constructor() {
super();
this.ApiKey = "****";
this.state = {
searchInput: "",
searchResult: null,
error: "",
isLoading: false
};
}
searchCity = async () => {
this.setState({
isLoading: true
});
const url = `http://api.openweathermap.org/data/2.5/weather?q=${searchInput}&units=metric&appid=${
this.ApiKey
}`;
await fetch(url)
.then(res => res.json())
.then(responseJson =>
this.setState({
isLoading: false,
searchResult: {
name: responseJson.name,
country: responseJson.sys.country,
main: responseJson.weather[0].main,
description: responseJson.weather[0].description,
temp: responseJson.main.temp
}
})
)
.catch(error => this.setState({ error }));
};
render() {
const { searchInput, searchResult, isLoading, error } = this.state;
if (!isLoading) {
return (
<View
style={{
backgroundColor: "#2b3654",
flex: 1,
justifyContent: "center",
alignItems: "center"
}}
>
{isLoading && <Text style={styles.Text}> Loading...</Text>}
<ActivityIndicator size="large" color="00ff00" />
</View>
);
} else if (error) {
return (
<View>
<Text>{error}</Text>
</View>
);
}
if (searchResult) {
return (
<LinearGradient colors={["rgba(0,0,0,0.05)", "rgba(0,0,0,0)"]}>
<View>
<Text>{searchResult.name}</Text>
<Text> {searchResult.main}</Text>
<Text> {searchResult.description}</Text>
<Text> {searchResult.temp}</Text>
</View>
</LinearGradient>
);
} else {
return (
<View style={styles.container}>
<View style={styles.searchSection}>
<TouchableOpacity onPress={this.searchCity}>
<Icon
style={styles.searchIcon}
name="ios-search"
size={15}
color="#fff"
/>
</TouchableOpacity>
<TextInput
style={styles.input}
placeholder="Find Your City.."
placeholderTextColor="#fff"
underlineColorAndroid="transparent"
autoCapitalize="none"
onChangeText={searchInput => {
this.setState({ searchInput });
}}
onSubmitEditing={this.searchCity}
value={searchInput}
/>
</View>
</View>
);
}
}
}

You need to use this.state.searchInput
The line should be:
const url = `http://api.openweathermap.org/data/2.5/weather?q=${this.state.searchInput}...`;

The problem is in your URL, you have used searchInput there...
use this.state.searchInput
or you can use destructuring
const { searchInput } = this.state;
const url = `http://api.openweathermap.org/data/2.5/weather?q=${searchInput}&units=metric&appid=${
this.ApiKey
}`;

Related

undefinded is not an object

Hello I'm facing with render error in my movie app during printing results for movie searching. Im working in React-Native 0.70.5. Here is some code for this activity
`
import React,{useState,useEffect} from 'react';
import axios from 'axios';
import { View, StyleSheet, Text, TextInput,ScrollView } from "react-native";
const Search = () => {
const apiurl="https://api.themoviedb.org/3/search/movie?api_key=XXX"
const [state,setState] = useState({
s: "Enter a movie",
results:[]
});
const search = () => {
axios(apiurl + "&query="+ state.s).then(({ data }) => {
let results = data.search;
console.log(data);
setState(prevState => {
return{...prevState, results: results }
})
})
}
return (
<View>
<TextInput
onChangeText={text => setState(prevState => {
return {...prevState, s:text}
})}
onSubmitEditing={search}
value={state.s}
/>
<ScrollView>
{state.results.map(result =>(
<View key={result.id}>
<Text>{result.title}</Text>
</View>
))}
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
center: {
flex: 1,
justifyContent: "center",
alignItems: "center",
textAlign: "center",
},
});
export default Search;
`
How to change the construction of this function to print movie titles corectly ?
This is just an example and not the best way to do it.
You need a success flag, something like this:
const [success,setSuccess] = useState(false);
const search = () => {
axios(apiurl + "&query="+ state.s).then(({ data }) => {
let results = data.results;
console.log(data);
setState(prevState => {
return{...prevState, results: results }
})
setSuccess(true);
})
}
<ScrollView>
{success && state.results.map(result =>(
<View key={result.id}>
<Text>{result.title}</Text>
</View>
))}
</ScrollView>
I am not sure but you can try this below ScrollView code...
<ScrollView>
{state.results.length>0 && (state.results.map((result) =>(
<View key={result.id}>
<Text>{result.title}</Text>
</View>
)))}
</ScrollView>
use optional chaining. Might be sometimes you don't get result.
<ScrollView>
{state?.results?.map(result =>(
<View key={result?.id}>
<Text>{result?.title}</Text>
</View>
))}
</ScrollView>
Let me know is it helpful or not

render data in FlatList React Native (expo cli) from firebase realtime database?

I'm working on a ToDo app that is connected to the Firebase real-time database. Everything works fine. I can also store data in the Firebase database, but the problem is that I cannot get any data from the database. I want to render data in ScrollView so that the data can be displayed in ScrollView when I open my app.
I'm getting error: ReferenceError: noteArray is not defined <FlatList data={noteArray}
I have uploaded my whole code [codesandbox.io/s/stupefied-snowflake-1lddp?file=/src/App.js][1]
Main.js
import React, { Component } from "react";
import {
StyleSheet,
Text,
View,
TextInput,
TouchableOpacity,
FlatList
} from "react-native";
import Note from "./note";
import firebase from "./firebase";
export default class Main extends React.Component {
constructor(props) {
super(props);
this.state = {
noteArray: [],
noteText: ""
};
}
componentDidMount() {
this.listenForNotes();
}
listenForNotes() {
firebase
.database()
.ref(`todos`)
.on("value", function (snapshot) {
const notes = [];
snapshot.forEach((child) => {
notes.push({
note: child.val().name,
date: child.val().date,
key: child.key
});
});
this.setState({
noteArray: notes
});
});
}
adTask() {
if (this.state.noteText) {
var date = new Date();
var database = firebase.database().ref("todos");
var key = database.push().key;
var todo = {
date:
date.getDay() +
"/" +
(date.getMonth() + 1) +
"/" +
date.getFullYear(),
note: this.state.noteText,
key: key
};
database.child(key).set(todo);
this.setState({ noteText: "" });
}
}
deleteNote(key) {
// your delete note function
}
render() {
return (
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.headerText}>Todo</Text>
</View>
<FlatList
data={this.state.noteArray}
renderItem={({ item, index }) => {
return (
<Note
key={item.key}
note={item.note}
date={item.date}
deleteMethod={() => this.deleteNote(item.key)}
/>
);
}}
key={(item) => `${item.key}`}
/>
<View style={styles.footer}>
<TextInput
style={styles.textInput}
onChangeText={(noteText) => this.setState({ noteText })}
value={this.state.noteText}
placeholder="Enter Task"
placeholderTextColor="white"
underlineColorAndroid="transparent"
></TextInput>
</View>
<TouchableOpacity
onPress={this.adTask.bind(this)}
style={styles.addButton}
>
<Text style={styles.addButtonText}>Add</Text>
</TouchableOpacity>
</View>
);
}
}
note.js
import React from "react";
import { StyleSheet, Text, View, TouchableOpacity } from "react-native";
export default class Note extends React.Component {
constructor(props) {
super(props);
}
render() {
const { note, date, key, deleteMethod } = this.props;
return (
<View key={key} style={styles.note}>
<Text style={styles.noteText}>{note}</Text>
<Text style={styles.noteDate}>{date}</Text>
<TouchableOpacity onPress={deleteMethod} style={styles.noteDelete}>
<Text style={styles.noteDeleteText}>
<AntDesign name="delete" size={24} color="black" />
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
note: {
position: "relative",
padding: 20,
paddingRight: 100,
borderBottomWidth: 2,
borderBottomColor: "#ededed"
},
noteText: {
fontWeight: "bold",
fontSize: 18,
paddingLeft: 20,
borderLeftWidth: 10,
borderLeftColor: "#e91e63"
},
noteDate: {
paddingLeft: 20,
borderLeftWidth: 10,
borderLeftColor: "#e91e63"
},
noteDelete: {
position: "absolute",
justifyContent: "center",
alignItems: "center",
backgroundColor: "#2980b9",
padding: 10,
top: 10,
bottom: 10,
right: 10
},
noteDeleteText: {
color: "white"
}
});
[1]: http://codesandbox.io/s/stupefied-snowflake-1lddp?file=/src/App.js
it should be this.state.noteArray since noteArray is a state variable.
there are couple of errors in the code sandbox
<FlatList
data={noteArray}
renderItem={({ item, index }) => {
should be
<FlatList
data={this.state.noteArray}
renderItem={({ item, index }) => {
and key, should be item.key:
deleteMethod={() => this.deleteNote(key)}
should be
deleteMethod={() => this.deleteNote(item.key)}
this.setState doesn't exist is because you have a function instead of an array function. change it to the following should work:
.on("value", snapshot => {
const notes = [];
snapshot.forEach((child) => {
notes.push({
note: child.val().name,
date: child.val().date,
key: child.key
});
});
this.setState({noteArray: notes});
});

How to get params in other App Container - React Navigation?

I want to use the params I passed to Profile Screen and he is in a separate App Container,
And I create TopTabs and put it in a specific AppContainer because I don't have any way to use it in a one AppContainer so how I Get these Params from another AppContainer?
So My Code here's
First thing, now I'm in the Map Screen and want to navigate to profile screen and pass some params like this
this.props.navigation.navigate('ProviderProfile', {
providerId: marker.id,
providerName: marker.name,
providerService: marker.service,
gKey: marker.gKey,
token: marker.token._55,
region: region
}
And here is Profile Screen, Contain let's say Card and TobTabs "I wrap it in a separate AppContainer"
and want to use params I passed in these TopTabs "every single tab" so how to handle these OR pass these params to every single Tab?
ProviderProfile.js
import React, { Component } from "react";
import Icon from "react-native-vector-icons/Ionicons";
import firebase from "react-native-firebase";
import { createAppContainer } from "react-navigation";
import { NavTabs } from "./ProviderTabs/NabTabs";
import { View, Text, StyleSheet, TouchableOpacity, Image } from "react-native";
console.disableYellowBox = true;
class ProviderProfile extends Component {
static navigationOptions = ({ navigation }) => {
const { state } = navigation;
return {
title: ` ${state.params.providerName}` || "profile"
};
};
constructor(props) {
super(props);
this.state = {
providerId: this.props.navigation.getParam("providerId"),
providerService: this.props.navigation.getParam("providerService"),
providerName: this.props.navigation.getParam("providerName"),
gKey: this.props.navigation.getParam("gKey"),
token: this.props.navigation.getParam("token"),
region: this.props.navigation.getParam("region"),
fav: false
};
}
_addToFavorite = () => {
const { providerName, providerService, providerId, fav } = this.state;
const currentUser = firebase.auth().currentUser.uid;
this.setState({ fav: !fav });
const ref = firebase
.database()
.ref(`favorites/${currentUser}/${providerId}`);
if (!fav) {
ref
.set({
ProviderId: providerId,
providerName: providerName,
providerService: providerService
})
.then(() => alert("Great, Added to your favorite list"));
} else {
ref.remove();
}
};
render() {
const {
providerName,
providerService,
providerId,
fav,
gKey,
region,
token
} = this.state;
return (
<View style={styles.container}>
{/* <Text>{gKey}</Text> */}
<Image
resizeMode="contain"
source={require("../assets/marker.png")}
/>
<View>
<View>
<Icon
name={`ios-heart${fav ? "" : "-empty"}`}
size={35}
color="#f00"
onPress={this._addToFavorite}
/>
</View>
<Text>
<Icon name="ios-star" size={20} color="#f2ba13" />
<Icon name="ios-star" size={20} color="#f2ba13" />
<Icon name="ios-star" size={20} color="#f2ba13" />
<Icon name="ios-star-half" size={20} color="#f2ba13" />
<Icon name="ios-star-outline" size={20} color="#f2ba13" />
</Text>
<Text style={{ fontSize: 19, color: "#000", padding: 5 }}>
{providerName}
</Text>
<Text>
Service: <Text>{providerService}</Text>
</Text>
<View style={{ flexDirection: "row", marginTop: 10 }}>
<TouchableOpacity
onPress={() => alert("Message")}
>
<Text>
Message
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() =>
this.props.navigation.navigate("Order", {
providerName,
providerId,
providerService,
gKey,
token,
region
})
}
>
<Text
>
Send Order
</Text>
</TouchableOpacity>
</View>
</View>
<Roots /> // Here's Tabs
</View>
);
}
}
const Roots = createAppContainer(NavTabs);
export default ProviderProfile;
And Here is a Tabs Screen "NavTabs"
import {
createMaterialTopTabNavigator,
} from "react-navigation";
import AboutScreen from "./About";
import GalaryScreen from "./Galary";
import ReviewsScreen from "./Reviews";
export const NavTabs = createMaterialTopTabNavigator(
{
About: { screen: AboutScreen },
Galaty: { screen: GalaryScreen },
Reviews: { screen: ReviewsScreen }
},
{
tabBarOptions: {
activeTintColor: "#fff",
inactiveTintColor: "#ddd",
tabStyle: {
justifyContent: "center"
},
indicatorStyle: {
backgroundColor: "#fcc11e"
},
style: {
backgroundColor: "#347ed8"
}
}
}
);
As you see, I want to use the username in Tab "About"
or other Tabs
Send params:
this.props.navigation.navigate('RouteName', { /* params go here */ })
Get params:
this.props.navigation.getParam(paramName, defaultValue)
Example:
this.props.navigation.navigate('NameListScreen', { names:["John","Mary"] })
let params = this.props.navigation.getParam(names, [])
I haven't use React Navigation myself but in their documentation say you can pass props to App Containers, so as you have defined the state with the props from the MapScreen you should probably pass them as props where you have defined your NavTabs Component as <Roots />
Also, there is another alternative to want to achieve as they present in here and it will be done in a redux way.

Fix Header and Searchbar with Flat list is not working properly

here in my code I am using Fixheader and Searchbar, but I'm trying to put searchbar below header and Header should be fixed .
One more problem is there,After entering anything in search bar then data is coming on FlatList .
Please help me for that , When I'm writing in searchbar or header outside the its generating error .
import React, { Component } from "react";
import {
View,
Text,
TextInput,
FooterTab,
Button,
TouchableOpacity,
ScrollView,
StyleSheet,
ActivityIndicator,
Header,
FlatList
} from "react-native";
import { Icon } from "native-base";
import { createStackNavigator } from "react-navigation";
import { SearchBar } from "react-native-elements";
export default class RenderList extends Component {
static navigationOptions = {
title: "Selected Item",
header: null
};
constructor() {
super();
this.state = {
data: "",
loading: true,
search: "",
searchText: "",
filterByValue: ""
};
}
componentDidMount() {
this.createViewGroup();
}
createViewGroup = async () => {
try {
const response = await fetch("http://example.com",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
password: "admin",
username: "admin",
viewall: "false",
id: [4],
startlimit: "0",
valuelimit: "10"
})
}
);
const responseJson = await response.json();
const { groupData } = responseJson;
this.setState({
data: groupData,
loading: false
});
} catch (e) {
console.error(e);
}
};
clickedItemText(clickedItem) {
this.props.navigation.navigate("Item", { item: clickedItem });
}
updateSearch = search => {
this.setState({ search });
};
keyExtractor = ({ id }) => id.toString();
keyExtractor = ({ name }) => name.toString();
renderItem = ({ item }) => (
<TouchableOpacity
style={styles.item}
activeOpacity={0.4}
onPress={() => {
this.clickedItemText(item);
}}
>
<Text style={styles.ListText}>Hospital Id {item.id}</Text>
<Text>Hospital Name {item.name}</Text>
</TouchableOpacity>
);
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "86%",
backgroundColor: "#CED0CE"
}}
/>
);
};
onSearchInputChange = text => {
const filterByValue = this.state.data.filter(x =>
x.name.toLowerCase().includes(text.toLowerCase())
);
this.setState({
searchText: text,
filterByValue
});
};
Render_FlatList_Sticky_header = () => {
var Sticky_header_View = (
<View style={styles.header_style}>
<Text style={{ textAlign: "center", color: "#000000", fontSize: 22 }}>
{" "}
FlatList Sticky Header{" "}
</Text>
</View>
);
return Sticky_header_View;
};
render() {
const { loading, data, filterByValue } = this.state;
return (
<ScrollView>
<View style={styles.container1}>
<SearchBar
lightTheme
onChangeText={this.onSearchInputChange}
value={this.state.searchText}
//onClearText={someMethod}
icon={{ type: "font-awesome", name: "search" }}
placeholder="Type Here..."
/>
{/* <TextInput style={styles.Searchbar}
onChangeText={this.onSearchInputChange}
value={this.state.searchText}
/> */}
{this.state.loading ? (
<ActivityIndicator size="large" />
) : (
<FlatList
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
ItemSeparatorComponent={this.renderSeparator}
data={filterByValue}
ListHeaderComponent={this.Render_FlatList_Sticky_header}
stickyHeaderIndices={[0]}
// ListHeaderComponent={this.render_FlatList_header}
/>
)}
</View>
</ScrollView>
);
}
}

onSubmitEditing never fires?

Really simple question, why isn't onSubmitEditing firing when I hit 'Search' on the virtual keyboard?
Currently there are no errors thrown and the console.log in onSearch() never fires.
I'm using the EXPO SDK v.29.
import React from 'react';
import { StyleSheet, Text, View, TextInput, ScrollView, Image } from 'react-native';
import { WebBrowser } from 'expo';
import Icon from 'react-native-vector-icons/Ionicons';
import Styles from 'app/constants/Styles';
import Vars from 'app/constants/Vars';
import Menu from 'app/components/Menu';
import MiniMap from 'app/components/MiniMap';
import NewsList from 'app/components/NewsList';
import {get, post} from 'app/helpers/api';
export default class HomeScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: (<Image style={{width: 132, height: 30}} source={require('./../../assets/images/header_image.png')}/>)
};
};
constructor(props) {
super(props);
this.state = {
menu: [],
loadingMenu: true,
searchString: '',
};
}
onMenuPress = (item) => {
let next;
let route = item.page_type.slice(4);
if(route == "PageExternal") {
WebBrowser.openBrowserAsync(item.page.url);
} else {
data = item.page;
if(item.children.length > 0) {
route = 'Menu';
data = item.children;
}
this.props.navigation.navigate(route, {
data: data,
title: item.title
});
}
}
onSearch = (e) => {
console.log('onSearch', e);
//WebBrowser.openBrowserAsync('https://www.1177.se/Halland/Sok/?q=Diabetes&submitted=true');
}
async componentDidMount() {
console.log('Eat my shorrs');
menuitems = await get('content/menu');
this.setState({
menu: menuitems,
loadingMenu: false,
})
//this._getMenu();
}
render() {
return (
<ScrollView style={Styles.whiteBackground}>
<View style={[Styles.blueBackground, Styles.topPadding, Styles.horizontalPadding]}>
<View style={[Styles.searchBox, Styles.bottomMargin]}>
<View style={Styles.searchField}>
<TextInput
style = {Styles.searchInput}
placeholder = "Sök sjukdom/behandling"
onSubmitEditing = {(e) => (this.onSearch(e))}
underlineColorAndroid = "transparent"
returnKeyLabel = "Sök på 1177"
returnKeyType = "search"
/>
<Icon style = {Styles.searchIcon} name = "ios-search" size={18}/>
</View>
<Text style={[Styles.searchLabel]}>Söksvaren kommer från 1177.se</Text>
</View>
<Menu
data={this.state.menu}
loading={this.state.loadingMenu}
style={Styles.topPadding}
onItemPress={this.onMenuPress}
/>
</View>
<Text style={[Styles.h1, Styles.blackText, Styles.horizontalPadding]}>Hitta till oss</Text>
<MiniMap navigation={this.props.navigation}></MiniMap>
<Text style={[Styles.h1, Styles.blackText, Styles.horizontalPadding]}>Nyheter</Text>
<NewsList navigation={this.props.navigation}></NewsList>
</ScrollView>
);
}
}
<TextInput
onSubmitEditing = {(event) => (this.onSearch(event.nativeEvent.text))}
multiline={false}
/>
It does not work when multiline={true} is specified, perhaps your styles has that. See Documentation
You will find your text with event.nativeEvent.text
Try changing
onSubmitEditing = {(e) => (this.onSearch(e))}
to
onSubmitEditing = {this.onSearch}
Then keep
onSubmitEditing = {(e) => this.onSearch(e)}
like this and try by changing the function like below
function onSearch(e) {
console.log('onSearch', e);
//WebBrowser.openBrowserAsync('https://www.1177.se/Halland/Sok/?q=Diabetes&submitted=true');
}
Hope this will work
Check this out
https://snack.expo.io/#raajnadar/submit-text-input
Render method
render() {
return (
<View style={styles.container}>
<TextInput
placeholder="Sök sjukdom/behandling"
onSubmitEditing={this.onSearch}
underlineColorAndroid="transparent"
returnKeyLabel="Sök på 1177"
returnKeyType="search"
style={{ width: '100%', textAlign: 'center' }}
/>
</View>
);
}
On submit function
onSearch() {
console.log('onSearch')
}

Categories

Resources