I have created a form to upload the image and text field on the home screen but I am facing a problem that it's not updating the array and validation is failing due to that. I think something wrong with my implementation
AddPost.js
const validationSchema = Yup.object({
title: Yup.string().required().min(5).max(15).label("Title"),
des: Yup.string().required().min(15).max(200).label("Description"),
image: Yup.array().required().label("Image"),
});
class AddPost extends Component {
render() {
return (
<Formik
initialValues={{ title: "", des: "", image: [] }}
onSubmit={(values, actions) => {
actions.resetForm();
this.props.addPost(values);
}}
validationSchema={validationSchema}
>
{(value) => (
<View>
<FormImage />
<Text style={styles.error}>
{value.touched.image && value.errors.image}
</Text>
<TextInput
placeholder="Title"
onChangeText={value.handleChange("title")}
style={styles.input}
value={value.values.title}
onBlur={value.handleBlur("title")}
/>
<Text style={styles.error}>
{value.touched.title && value.errors.title}
</Text>
Here is my form field I think everything is right here
home.js
class Home extends Component {
state = {
modal: false,
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
],
image: null,
};
addPost = (posts) => {
posts.key = Math.random().toString();
this.setState.post((currentPost) => {
return [posts, ...currentPost];
});
this.state.modal();
};
render() {
return (
<Screen style={styles.screen}>
<Modal visible={this.state.modal} animationType="slide">
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.modalContainer}>
<AddPost addPost={() => this.addPost} />
</View>
</TouchableWithoutFeedback>
</Modal>
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<Card
title={item.title}
subTitle={item.des}
image={item.image}
onPress={() => this.props.navigation.navigate("Edit", item)}
/>
</>
I think something wrong with the addPost method because I did it before with function base that time I only added text to the list and its worked but in class base I don't know to do it I just try the same way I did in function base
FormImage.js
class FormImage extends Component {
state = {
image: null,
hasCameraPermission: null,
};
async componentDidMount() {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
this.setState({ hasCameraPermission: status === "granted" });
}
_pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
});
if (!result.cancelled) {
this.setState({ image: result.uri });
}
};
render() {
const { image } = this.state;
return (
<TouchableWithoutFeedback onPress={this._pickImage}>
<View style={styles.container}>
{!image && (
<MaterialCommunityIcons
color={colors.medium}
name="camera"
size={40}
/>
)}
{image && <Image style={styles.image} source={{ uri: image }} />}
</View>
</TouchableWithoutFeedback>
);
}
}
after submiting
Iam assuming your addPost function logic is wrong,
Try the below code
addPost = (posts) => {
posts.key = Math.random().toString();
this.setState((prevState) => {
return {...prevState, post: [...prevState.post, ...posts] };
});
this.state.modal();
};
Let me know incase you are getting the same error.
You are not updating images to formik so is normal you get the required error.
First in your AddPost Component pass down formikProps to FormImage component.
return (
<Formik
initialValues={{ title: "", des: "", image: [] }}
onSubmit={(values, actions) => {
// actions.resetForm(); --> comment this
this.props.addPost(values);
}}
validationSchema={validationSchema}
>
{(value) => (
<View>
<FormImage formikProps={value}/>
<Text style={styles.error}>
{value.touched.image && value.errors.image}
</Text>
<TextInput
placeholder="Title"
onChangeText={value.handleChange("title")}
style={styles.input}
value={value.values.title}
onBlur={value.handleBlur("title")}
/>
<Text style={styles.error}>
{value.touched.title && value.errors.title}
</Text>
In FormImage use that formikProps and call setFieldValue("image", result.uri) to update formik value for image.
class FormImage extends Component {
state = {
image: null,
hasCameraPermission: null,
};
async componentDidMount() {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
this.setState({ hasCameraPermission: status === "granted" });
}
_pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
});
if (!result.cancelled) {
this.setState({ image: result.uri });
this.props.formikProps.setFieldValue("image", result.uri);
}
};
render() {
const { image } = this.state;
return (
<TouchableWithoutFeedback onPress={this._pickImage}>
<View style={styles.container}>
{!image && (
<MaterialCommunityIcons
color={colors.medium}
name="camera"
size={40}
/>
)}
{image && <Image style={styles.image} source={{ uri: image }} />}
</View>
</TouchableWithoutFeedback>
);
}
}
In home
addPost = (posts) => {
console.log('add post');
posts.key = Math.random().toString();
this.setState((prevState) => {
return {...prevState, post: [...prevState.post, ...posts], modal:
true };
});
// this.state.modal();
};
Related
export default class AchieveScreen extends ValidationComponent{
constructor(props) {
super(props)
this.state = {
visible: false,
filter: 1,
date: new Date(),
selected: new Date(),
loaded: false,
data: [],
feedbackText:"",
target:[],
refreshing:false,
refreshValue:1
}
}
handleUpdate = async () => {
this.setState({ loaded: false })
await this.getter()
this.forceUpdate();
};
GetData = async () => {
const {date,selected}=this.state
const data = await GetAchieve()
if (data.status == 200) {
this.setState({
data: data.data,
target:data.data !== null ? data.data.filter((achieve) => achieve.date.includes(selected)) : null,
loaded: true,
})
}
}
componentDidMount() {
this._unsubscribe = this.props.navigation.addListener('focus',() => {
console.log('ok')
const UserStatus=this.status()
if(UserStatus){
this.GetData()
}
});
}
_onRefresh=async()=> {
try {
this.setState({refreshing: true});
this.setState(({ refreshValue }) => ({
refreshValue: refreshValue + 1,
}));
this.setState({refreshing: false});
} catch (error) {
throw error
}
}
componentWillUnmount() {
this._unsubscribe();
}
shouldComponentUpdate(nextProps, nextState) {
if(this.state.data != nextState.data){
console.log('data re')
return true;
}
if(this.state.refreshValue != nextState.refreshValue || this.state.selected != nextState.selected || this.state.target != nextState.target ){
console.log('refreshing value')
return true;
}
return false
}
sendFeedBack=async()=>{
const {feedbackText} = this.state
this.validate({
feedbackText: {minlength:3, maxlength:4000},
});
if(!this.isFieldInError('feedbackText')){
const request = await feedback(feedbackText)
if(request.status == 200){
this.setState({
feedbackText:"",
visible:false
})
}
}
}
flag = (date) => {
items = this.state.data !== null ? this.state.data.filter((achieve) => achieve.date.includes(date)) : null
let Professional = false
let Personal = false
if (!!items) {
items.map(item => {
if (item.flag == 1) { Professional = true } else if (item.flag == 2) { Personal = true }
})
if (Professional && Personal) {
return <>
<Text> <Icon name="flag-o" size={10} color="#ff6666" /> </Text>
<Text> <Icon name="star-o" size={10} color="#cc80ff" /> </Text>
</>
} else if (Professional) {
return <Text> <Icon name="flag-o" size={10} color="#ff6666" /> </Text>
} else if (Personal) {
return <Text> <Icon name="star-o" size={10} color="#cc80ff" /> </Text>
}
}
}
week = () => {
const { date, selected,loaded } = this.state
const week = this.state.date.week()
if(loaded){
return (
<>
{week.map((day, index) => {
return (
selected === week[index].plenaDiem ?
<LinearGradient key={index} colors={['#EBDDFD', '#DFDCFF']} start={[0, 1]} end={[1, 0]} style={{ borderRadius: 12 }}>
<TouchableOpacity
key={index}
style={[styles.weekday]}
onPress={() => { this.setState({ selected: week[index].plenaDiem }) }}
disabled={week[index].enable}
>
<Text style={styles.name} >{week[index].dies}</Text>
<Text style={[styles.num, { color: week[index].color }]} >{week[index].diem}</Text>
<View style={styles.flags}>
{this.flag(week[index].plenaDiem)}
</View>
</TouchableOpacity>
</LinearGradient>
:
<TouchableOpacity
key={index}
style={[styles.weekday]}
onPress={() => {
console.log(this.state.target)
this.setState({
selected: week[index].plenaDiem,
target:this.state.data !== null ? this.state.data.filter((achieve) => achieve.date.includes(week[index].plenaDiem)) : null,
})
}}
disabled={week[index].enable}
>
<Text style={styles.name} >{week[index].dies}</Text>
<Text style={[styles.num, { color: week[index].color }]} >
{week[index].diem}
</Text>
<View style={styles.flags}>
{this.flag(week[index].plenaDiem)}
</View>
</TouchableOpacity>
)
})
}
</>
)
}
}
render() {
const { data, date, visible, selected, filter, loaded,feedbackText,refreshing,target } = this.state
// let render = data !== null ? data.filter((achieve) => achieve.date.includes(selected)) : null
// if (filter !== 3 && render !== null) {
// render = render.filter((item) => item.flag == filter)
// }
return (
<>
<View style={styles.header} >
<View style={styles.top}>
<View style={styles.icon}>
<Image source={require('../../assets/header/CalendarIcon.png')} />
<Text style={styles.day}>{date.day()}</Text>
</View>
<View style={styles.items}><Image source={require('../../assets/header/medalLogo.png')} /></View>
<View style={styles.items}><IconButton icon='question' style={styles.question} color={"#000"} size={16} onPress={() => this.setState({ visible: true })} /></View>
</View>
<Modal
visible={visible}
backdropStyle={styles.backdrop}
onBackdropPress={() => this.setState({ visible: false })}>
<Card disabled={true} style={{backgroundColor:"#FFF",width:wp('90%'),borderRadius:10}}>
<Input
name='feedbackText'
value={feedbackText}
style={styles.feedbackText}
multiline={true}
maxLength={4000}
placeholder="tell us about you expermenit"
onChangeText={(text) => { this.setState({
feedbackText: text,
}) }}
/>
<Button
disabled={feedbackText.length<3?true:false}
onPress={() => {this.sendFeedBack()}}>
subimt
</Button>
</Card>
<View style={[styles.close]}>
<AntDesign name={"closecircleo"} color="#000" onPress={() => this.setState({ visible: false })} size={25} />
</View>
</Modal>
<ScrollView
contentContainerStyle={styles.scrollView}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={this._onRefresh.bind(this)}
/>
}
>
<View style={styles.month}>
<Text style={styles.monthName}>{date.monthName()}</Text>
</View>
<View style={styles.week}>
{loaded ? this.week() : <LoadingScreen/>}
</View>
</ScrollView>
</View>
<View style={styles.container} >
<View style={styles.achieve}>
<View>
{/* <SwitchSelector
options={options}
initial={0}
style={styles.switch}
buttonColor={"#fff"}
textColor={"#AB9CB3"}
selectedColor={"#000"}
buttonMargin={3}
imageStyle={styles.switchicon}
backgroundColor={"#F0F1F8"}
onPress={value => this.setState({ filter: value })}
/> */}
</View>
<View style={styles.count}>
<Text style={styles.countText}>you have achieved {target !== null ? target.length : null}</Text>
</View>
</View>
<View style={styles.cards}>
<Cards type={true} data={target} storage={data} handle={this.handleUpdate} />
</View>
</View>
</>
)
}
}
this is calendar component when run it no thing to display but data can be in console log. i can show data there, I need to hit Ctrl+s to refresh expo 'fast refresh' to show data in simulator
I have load Logic in render section but issue is still need fix
any suggestions?
this screen before hit Ctrl+s data is already in state but not rendering "first run"
here after hit Ctrl+s to refresh screen to show data
I made a edit screen and trying to update the value of post through navigation v4 by using getParams and set setParams but when I change the old value and click save buttton to save it, it's not updating it and no error is showing either. It's still showing old values. Can someone please help me, below is my code
EditScreen.js
class EditScreen extends Component {
render() {
const { params } = this.props.navigation.state;
return (
<KeyboardAvoidingView
behavior="position"
keyboardVerticalOffset={Platform.OS === "ios" ? 0 : 100}
>
<Image
style={styles.image}
source={this.props.navigation.getParam("image")}
/>
<View style={styles.detailContainer}>
<AppTextInput
value={this.props.navigation.getParam("title")}
onChangeText={(text) =>
this.props.navigation.setParams({ title: text })
}
/>
<AppTextInput
value={this.props.navigation.getParam("des")}
onChangeText={(text) =>
this.props.navigation.setParams({ des: text })
}
/>
</View>
<AppButton
text="Save"
style={styles.button}
onPress={() => {
this.props.navigation.getParam("onEdit");
this.props.navigation.goBack();
}}
/>
</KeyboardAvoidingView>
Home.js
class Home extends Component {
state = {
modal: false,
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
],
};
onEdit = (data) => {
const newPosts = this.state.post.map((item) => {
if (item.key === data.key) return data;
else return item;
});
this.setState({ post: newPosts, editMode: false });
};
render() {
return (
<Screen style={styles.screen}>
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<TouchableOpacity
activeOpacity={0.7}
onPress={() =>
this.props.navigation.navigate("Edit", {
image: item.image,
title: item.title,
des: item.des,
onEdit: this.onEdit,
})
}
style={styles.Edit}
>
<MaterialCommunityIcons
name="playlist-edit"
color="green"
size={35}
/>
</TouchableOpacity>
<Card onPress={() => this.props.navigation.push("Details", item)}>
<Image style={styles.image} source={item.image} />
<View style={styles.detailContainer}>
<Text style={styles.title} numberOfLines={1}>
{item.title}
</Text>
<Text style={styles.subTitle} numberOfLines={2}>
{item.des}
</Text>
</View>
</Card>
</>
I recommend you to keep the data in the component state:
constructor(props) {
super(props);
// get the data that you need from navigation params
const { key, title, ..} = this.props.navigation.state.params
this.state = {key, title, ..}
}
then :
<AppTextInput
value={this.state.title}
onChangeText={(text) =>
this.setState({ title: text })
}
/>
<AppButton
text="Save"
style={styles.button}
onPress={() => {
this.props.navigation.getParam("onEdit")(this.state);
this.props.navigation.goBack();
}}
/>
Maybe try this:
<AppButton
text="Save"
style={styles.button}
onPress={() => {
this.props.navigation.getParam("onEdit")(this.props.navigation.state.params);
this.props.navigation.goBack();
}}
/>
and:
this.props.navigation.navigate("Edit", {
key: item.key,
image: item.image,
title: item.title,
des: item.des,
onEdit: this.onEdit,
})
how can I access a single element from an array nested in a state like this
state = {
modal: false,
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
]
};
.....
<MyList.Provider
value={{
}}
>
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<TouchableOpacity
activeOpacity={0.7}
onPress={() => this.deleteItem(item)}
style={styles.Delete}
>
<MaterialCommunityIcons name="delete" color="red" size={30} />
</TouchableOpacity>
<TouchableOpacity
activeOpacity={0.7}
onPress={() => this.props.navigation.navigate("Edit", item)}
style={styles.Edit}
>
<MaterialCommunityIcons
name="playlist-edit"
color="green"
size={35}
/>
</TouchableOpacity>
<Card
title={item.title}
subTitle={item.des}
image={item.image}
onPress={() =>
this.props.navigation.navigate("Details", item)
}
/>
</>
)}
/>
</MyList.Provider>
how can I do this like this.state.post({title}) or some way else??
I need to use this values with context so I can share and change some particular data with between 2 screens. I know to pass data I need to use context or navigation.navigate("route name",item). But if I use navigation I won't able to edit it but how can I pass data in context value from array set, if I do this.state.post it will return whole list and if i do this.state.post[0].title it will return only title of that post. So how can i do this? Please help
You have to indicate the index of the object you’re trying to access in the array. For instance to access the first object in the array you can do this
this.state.post[0]
below is my solution which follows the logic i think you are trying to achieve. I have used a flatlist
Let me know if it helps
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
FlatList,
} from 'react-native';
export default class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
modal: false,
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
]
};
}
handleEdit(item) {
const { post } = this.state;
const extractIndex = post.findIndex(e => e.key === item.key);
const newPost = post[extractIndex];
this.props.navigation.navigate('Edit', { newPost })
this.setState({ post });
}
handleDelete(item) {
const { post } = this.state;
const newPost = post.filter(e => e.key !== item.key);
this.setState({ post: newPost });
}
renderItem = ({ item }) => {
return (
<View>
<Text>
{item.title}
</Text>
<TouchableOpacity key={item.key} onPress={this.handleEdit.bind(this, item)}>
<Text>Edit</Text>
</TouchableOpacity>
<TouchableOpacity key={item.key} onPress={this.handleDelete.bind(this, item)}>
<Text>Delete</Text>
</TouchableOpacity>
</View>
);
}
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.post}
renderItem={this.renderItem}
keyExtractor={(item, index) => index.toString()}
extraData={this.state}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
Use .map() function
Ex-
var cat_data = categories_list.map(function (item) {
var cat_data = categories_list.map(function (item) {
return {
name: item.Name,
thumb_url: item.PictureModel.ImageUrl,
cat_id: item.Id.toString(),
};
});
this.setState({
data: cat_data,
});
Is there any way to check if items are actually being rendered or not? In my code, I run a grapqhl query and then re-render some items accordingly. In my code, if there are users present, the showUsersfunction works correctly.
However, when there are no users the noUsersTextfunction is called as confirmed by console.logs but I don't see anything rendered on the screen. I thought it might be a styling issue but I also tried increasing the font or adding more items to the view - it's clearly not working. What could the issue be?
When the function noUserText is called, both isSubmitted& isNotFoundare printed as true. I am using this in my main jsx {isSubmitted && noUsersText(userData) && isNotFound}so I believe the text should show up.
const [isSubmitted, setIsSubmitted] = useState(false);
const [isNotFound, setIsNotFound] = useState(false);
const [userData, setUserData] = useState<UsersLazyQueryHookResult>('');
const noUsersText = React.useCallback(
(data: UsersLazyQueryHookResult) => {
console.log('isSubmitted', isSubmitted);
console.log('Not Found', isNotFound);
if (data) {
if (data.users.nodes.length == 0) {
return (
<View>
<Text style={styles.noUsers}>No Users Found</Text>
</View>
);}
}
},
[userData],
);
const showUsers = React.useCallback(
(data: UsersLazyQueryHookResult) => {
if (data) {
return (
<View style={styles.friends}>
{data.users.nodes.map(
(item: { firstName: string; lastName: string; id: number }) => {
const userName = item.firstName
.concat(item.lastName);
return (
<View
style={styles.item} key={item.id}>
<View style={styles.addButtonContainer}>
<Button
rounded
style={styles.addButton}
onPress={() => {
addFriend(Number(item.id));
setIsSubmitted(false);
setUserData(null);
}}>
</Button>
</View>
</View>
);
},
)}
</View>
);
}
},
[createUserRelationMutation, userData],
);
const addFriend = React.useCallback(
(id: Number) => {
createUserRelationMutation({
variables: {
..,
},
});
},
[createUserRelationMutation],
);
const getFriendId = React.useCallback(
(data: UsersLazyQueryHookResult) => {
if (data) {
if (data.users.nodes.length == 0) {
setUserData(data);
setIsNotFound(true);
//Alert.alert('User Not Found');
} else {
setUserData(data);
}
}
},
[addFriend],
);
const [loadUsers] = useUsersLazyQuery({
onCompleted: getFriendId,
onError: _onLoadUserError,
});
const handleSubmitForm = React.useCallback(
(values: FormValues, helpers: FormikHelpers<FormValues>) => {
setIsSubmitted(true);
console.log('Submitted');
loadUsers({
variables: {
where: { email: values.email },
},
});
values.email = '';
},
[loadUsers],
);
return (
<Modal
visible={showAddFriendEmailPage}
animationType="slide"
transparent={true}>
<SafeAreaView>
<View style={styles.container}>
<View style={styles.searchTopContainer}>
<View style={styles.searchTopTextContainer}>
<Text
style={styles.searchCancelDoneText}
onPress={() => {
toggleShowPage();
setIsSubmitted(false);
setUserData(null);
setIsNotFound(false);
}}>
Cancel
</Text>
<Text style={styles.searchTopMiddleText}>
Add Friend by Email
</Text>
<Text style={styles.searchCancelDoneText}>Done</Text>
</View>
<View>
<Formik
initialValues={initialValues}
onSubmit={handleSubmitForm}
validationSchema={validationSchema}>
{({ handleChange, handleBlur, handleSubmit, values }) => (
<View style={styles.searchFieldContainer}>
<View style={styles.form}>
<FieldInput
handleChange={handleChange}
handleBlur={handleBlur}
value={values.email}
placeholderText='a#example.com'
/>
</View>
<View style={styles.buttonContainer}>
<Button
rounded
style={styles.button}
onPress={handleSubmit}>
<Text style={styles.text}>Search </Text>
</Button>
</View>
</View>
)}
</Formik>
</View>
{isSubmitted && showUsers(userData)}
{isSubmitted && noUsersText(userData) && isNotFound}
</View>
</View>
</SafeAreaView>
</Modal>
);
};
React doesn't render boolean, undefined or null values. Also note that when you write conditional rendering like
{isSubmitted && noUsersText(userData) && isNotFound}
The result is returned on the first falsy value. Otherwise the last truthy value is returned
So in your case the above code return true instead of the View component
Change the above to
{isSubmitted && isNotFound && noUsersText(userData)}
and it should work
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
}`;