Text Input onSubmit while using fetch React Native - javascript

I am trying to update my state for nickname and email through textInput and then submit it through a post request to my server. Both keep coming back as undefined. I'm totalling lost as to what I'm doing wrong here.
export default class Add extends Component {
constructor(props){
super(props);
this.state ={
isLoading: true,
nickname: "",
email: ""
}
}
static navigationOptions = {
title: 'Add Contacts',
};
componentDidMount(){
this.setState({
isLoading: false
})
}
onSubmit = () => {
console.log('on submit')
return fetch(`...`, {
method: 'POST',
headers: {
'Accept': 'application/json, text/plain */*',
'Content-Type': 'application/json',
},
body: JSON.stringify(this.state)
})
.then((response) => response)
.then((responseJson) => {
return responseJson
})
.catch((error) => {
throw error;
})
}
render() {
const { navigate } = this.props.navigation;
if(this.state.isLoading){
return(
<View style={{flex: 1, padding: 20}}>
<ActivityIndicator/>
</View>
)
}
return(
<View
style={styles.container}
>
<Text
style={{fontSize:30}}>
New Contact
</Text>
<View>
<TextInput
ref= {(el) => { this.nickname = el; }}
onChangeText={(nickname) => this.setState({nickname}, function () {console.log('Nickname updated')})}
value={this.state.nickname}
/>
<TextInput
value={this.state.email}
onChangeText={(text) => this.setState({email: text})}
/>
</View>
<Button
text = {
<Text
style={{color:colors.textColor, textAlign: 'center'}}
>
Save
</Text>
}
onPress= { () => {
this.onSubmit()
navigate('Home')
}
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
marginTop: 20,
alignItems: 'center',
justifyContent: 'center',
}
});

.then((response) => response)
Should be:
.then((response) => response.json())
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Making_fetch_requests

Related

Formik InitialValues not changing to state defined values for Form React Native

I'm using an API call to return the values for an edit form. As it stands, formik is not populating the inputs with the values from the nested state object. I simply want to give the user the ability to edit/save their form and return back to the home screen. When I use value={this.state.application_form.first_name} for the input, it does set the value, but you cannot change it. How do I populate the formik form with existing values using the initialValue & state props?
I get an undefined error when using state.application_form.info_attributes.attribute or it doesn't load and set an attribute.
constructor(props) {
super(props);
this.state = {
application_form: {
id: '',
user_id: '',
info_attributes: {
prefix: '',
first_name: ''
}
},
};
}
componentDidMount() {
this.getToken()
.then(obj => axios.get(`http://127.0.0.1:3000/api/v1/retrieve_user/${obj.user_id}`, { headers: { Accept: 'application/json', 'X-User-Email': `${obj.email}`, 'X-User-Token': `${obj.authentication_token}` } }))
.then(response => {
this.setState({ user: JSON.stringify(response.data) });
this.setState({ user_id: JSON.parse(this.state.user).id.toString() })
fetch(`http://127.0.0.1:3000/api/v1/get_application_form/${this.state.user_id}`)
.then(response => response.json())
.then(data =>
this.setState({
application_form: {
id: String(data['id']),
user_id: String(data['user_id']),
personal_info_attributes: {
prefix: String(data['info']['prefix']),
first_name: String(data['info']['first_name']),
}
}
}))
})
.catch(error => {
console.error(error);
});}
Form.js
render() {
return (
<KeyboardAvoidingView behavior="padding">
<View style={{ paddingVertical: 5, paddingHorizontal: 14 }}>
<View style={{ backgroundColor: '#fff', width: Dimensions.get('window').width * 0.9, minHeight: 50, padding: 2, borderColor: 'gray', borderRadius: 4, borderWidth: 1, height: Dimensions.get('window').height * 0.8 }}>
<ScrollView>
<Formik
enableReinitialize initialValues={{ application_form: { info_attributes: { prefix: '', first_name: '' }, user_id: this.userId(), id: this.application_form.id } }} onSubmit={(values) => {
const { navigation } = this.props;
return axios({
url: `http://127.0.0.1:3000/api/v1/application_forms`,
method: 'PUT',
data: values,
}).then(response => {
navigation.navigate('Dashboard')
}).catch(err => {
showMessage({
message: "Unable to submit!",
description: "Testing",
type: 'danger'
})
})
}}>
{props => (
<View style={{ padding: 1 }}>
<Text>Prefix</Text>
<TextInput style={styles.input} onChangeText={text => props.setFieldValue('application_form.info_attributes.prefix', text)} />
<Text>First Name</Text>
<TextInput style={styles.input} onChangeText={text => props.setFieldValue('application_form.info_attributes.first_name', text)} />
<Text>Middle Name</Text>
<TextInput style={styles.input} onChangeText={text => props.setFieldValue('application_form.info_attributes.middle_name', text)} />
<Button onPress={props.handleSubmit} title="Submit" />
</View>
)}
</Formik>
</ScrollView>
</View>
</View>
</KeyboardAvoidingView>
)
}

How to successfully pass params between screens?

I have been reading a lot of answers on SO as well as GitHub issues trying to implement a solution, but have been unable to come up with a solution for this situation.
Here is a representation of my code:
class MeetingsScreen extends React.Component {
constructor(props) {
super(props)
this.state = {
upcomingMeeting: [],
refreshing: false
};
}
async handlePress() {
const user = await AsyncStorage.getItem('User');
this.props.navigation.navigate('WriteSummary', { id: user.id, type: 'submit' });
}
printUpcomingMeetings = () => {
return (<View style={styles.meeting}>
<Button
containerStyle={styles.meetingButton}
style={styles.meetingButtonText}
onPress={() => this.handlePress(user.id)}
Press me to write summary!
</Button>
</View>);
}
}
render () {
return (<View style={{flex:1}} key={this.state.refreshing}>
{ this.printUpcomingMeetings() }
</View>);
}
}
class WriteSummaryScreen extends React.Component {
constructor(props) {
super(props)
this.state = {
storageId: '',
normalId: -1,
type: '',
curSummary: ''
}
}
componentDidMount = () => {
const { params } = this.props.navigation.state;
const { id, type } = params ? params : null;
const storageId = 'summary_' + id;
this.setState({storageId:storageId});
this.setState({normalId:id});
this.setState({type:type});
AsyncStorage.getItem(storageId).then((value) => this.setSkipValue(value));
}
async setSkipValue (value) {
if (value !== null) {
this.setState({ 'curSummary': value });
} else {
this.setState({ 'curSummary': '' });
}
}
async saveSummary (text) {
this.setState({'curSummary': text});
await AsyncStorage.setItem(this.state.storageId, text);
}
async handleSubmit() {
const user = await AsyncStorage.getItem('User');
if (this.state.type === 'submit') {
// post insert
const postres = fetch (url + '/create-summary', {
method: 'POST',
body: JSON.stringify({
AppointmentId: this.state.normalId,
SummaryText: this.state.curSummary,
UserId: user.Id
}),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.catch((error) => {
console.error(error);
});
} else {
// post update
const postres = fetch (url + '/update-summary', {
method: 'POST',
body: JSON.stringify({
AppointmentId: this.state.normalId,
SummaryText: this.state.curSummary,
UserId: user.Id
}),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.catch((error) => {
console.error(error);
});
}
this.props.navigation.navigate('Meetings');
}
render () {
return <View style={{flex:1}}>
<View>
<View style={{height:25, backgroundColor: colors.vikingBlue}}></View>
<View style={{height:30, backgroundColor: colors.white}}></View>
<View style={{flexDirection:'row', backgroundColor: colors.white, alignItems:'center'}}>
<View style={{width:5}}></View>
<TouchableOpacity onPress={() => this.props.navigation.goBack()} activeOpacity={0.5}>
<Image style={{width:30, height:30}} source={require('./assets/icons8-back-50.png')} />
</TouchableOpacity>
<View style={{width:10}}></View>
<View style={{width:mainTitleWidth,textAlign:'center',alignItems:'center'}}>
<Text style={{fontSize:22}}>Settings</Text>
</View>
<TouchableOpacity onPress={() => this.props.navigation.navigate('HelpModal')} activeOpacity={0.5}>
<Image style={{width:30, height:30}} source={require('./assets/help.png')} />
</TouchableOpacity>
</View>
<View style={{height:30, backgroundColor: colors.white}}></View>
</View>
<TextInput
multiline
numberOfLines={6}
style={styles.summaryInput}
onChangeText={text => saveSummary(text)}
value={this.state.curSummary} />
<Button
containerStyle={styles.summaryButton}
style={styles.summaryButtonText}
onPress={this.handleSubmit()}>
Submit
</Button>
</View>
}
}
function HomeStack() {
return (
<Tab.Navigator
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Meetings" component={MeetingsScreen} />
<Tab.Screen name="Topics" component={TopicsScreen} />
</Tab.Navigator>
);
}
export default class AppContainer extends React.Component {
// Main rendering function. Always begins on the SplashScreen, which checks user login status and directs to Meetings. I left it out and the other Tab navigator screens for less clutter.
render() {
return (
<NavigationContainer>
<Stack.Navigator headerMode='none' initialRouteName='Splash'>
<Stack.Screen name='Splash' component={SplashScreen} />
<Stack.Screen name='Main' component={HomeStack} />
<Stack.Screen name='WriteSummary' component={WriteSummaryScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
};
I get the error TypeError: undefined is not an object (evaluating '_this7.props.navigation.state.params)' after pressing the button on MeetingsScreen and navigating to WriteSummaryScreen.
What confuses me is the screen is navigated to, so the data should have been passed. What am I missing?
You can access parametes like below if its class based component:
class WriteSummaryScreen extends React.Component {
const {id, type} = this.props.route.params;
//........
for the functional component:
const WriteSummaryScreen =({navigation, route})=>{
const {id, type} = route.params;
//..........
}
You can access the params that you have passed from a screen using the getParam function.
so you can use this code:
const id = this.props.navigation.getParam("id");
const type = this.props.navigation.getParam("type");
What ended up working for me was the following:
const id = this.props.route.params.id;
const type = this.props.route.params.type;

How do i get specific elements from webservice

I want to get specific the first two elements from a webservice and print it to a console it is returning me 1000 items. Can anyone guide me on how I can print only the first two elements
import React from "react";
import {StyleSheet,View,ActivityIndicator,FlatList,Text,TouchableOpacity} from "react-native";
export default class Source extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
title: "Source Listing",
headerStyle: {backgroundColor: "#fff"},
headerTitleStyle: {textAlign: "center",flex: 1}
};
};
constructor(props) {
super(props);
this.state = {
loading: false,
items:[]
};
}
FlatListItemSeparator = () => {
return (
<View style={{
height: .5,
width:"100%",
backgroundColor:"rgba(0,0,0,0.5)",
}}
/>
);
}
renderItem=(data)=>
<TouchableOpacity style={styles.list}>
<Text style={styles.lightText}>{data.item.name}</Text>
<Text style={styles.lightText}>{data.item.email}</Text>
<Text style={styles.lightText}>{data.item.company.name}</Text>
</TouchableOpacity>
render(){
{
if(this.state.loading){
return(
<View style={styles.loader}>
<ActivityIndicator size="large" color="#0c9"/>
</View>
)}}
return(
<View style={styles.container}>
<FlatList
data= {this.state.dataSource}
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem= {item=> this.renderItem(item)}
keyExtractor= {item=>item.id.toString()}
/>
</View>
)}
}
const parseString = require('react-native-xml2js').parseString;
fetch('http://192.168.200.133/apptak_service/apptak.asmx/Get_Item_Master')
.then(response => response.text())
.then((response) => {
parseString(response, function (err, result) {
console.log(response[0],response[1])
});
}).catch((err) => {
console.log('fetch', err)
})
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff"
},
loader:{
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#fff"
},
list:{
paddingVertical: 4,
margin: 5,
backgroundColor: "#fff"
}
});
I want it to be print on the console then I will modify it later to display it on the app. I am struggling to get this done Please help
You are parsing the response as string. If you want to print the first two item in console, you can do it like this bellow:
fetch('http://192.168.200.133/apptak_service/apptak.asmx/Get_Item_Master')
.then((response) => {
console.log(response.data[0],response.data[1])
}).catch((err) => {
console.log('fetch', err)
})
Perhaps what you need is the result?
parseString(response, function (err, result) {
console.log(result) // not console.log(response)?
});
Using JavaScript
fetch("http://192.168.200.133/apptak_service/apptak.asmx/Get_Item_Master")
.then((r) => r.text())
.then((t) => (new window.DOMParser()).parseFromString(t, "text/xml"))
.then((d) => console.log(d))
.catch((e) => console.error(e));

Render fetch results after button is pressed

I have a list of articles which is fetching from server(json).There will be two server calls.What I meant is now I'm listing some article title (fetching from server1) within a Card.Below that there will be an add button for copy and pasting new article links(that will be saved to a different server).So I'm trying to append this newly added articles to my existing list(just like the same in pocket app).How can I do this?I've tried something like the below.But I'm getting error , may be a little mistake please help me to figure out.Since the render should happen only after button click(for viewing newly added ones).So state will also set after that right?How can I do that?
import {article} from './data'; //json
import AddNewarticle from './AddNewarticle';
class SecondScreen extends Component {
state= {
newarticle: []
};
// request for saving newly added article
onPressSubmit(){
fetch('www.mywebsite.com',{
method: 'POST',
headers:{
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: this.state.url,
})
})
.then(response => response.json())
.then((responseData) => this.setState({newarticle: responseData}));
}
renderArticle(){
this.state.newarticle.message.map(newlist =>
<AddNewarticle key ={newlist.title} newlist={newlist} />
);
}
render(){
return(
<ScrollView>
{article.map(a =>
<CardSection>
<Text>
{a.title}</Text>
</CardSection>
{this.renderArticle()}
</ScrollView>
<Icon
raised
name="check"
type="feather"
color="#c1aba8"
iconStyle={{ resizeMode: "contain" }}
onPress={() => {
this.onPressSubmit();
}}
/>
);
}
Also my newarticle (json) is as follows.The response I'm getting from server after submitting new articles.
{
"message": {
"authors": [
"Zander Nethercutt"
],
"html": "<div><p name=\"c8e3\" id=\"c8e3\" class=\"graf graf--p graf--hasDropCapModel graf--hasDropCap graf--leading\">The presence of advertising in This is the power of branding.",
"title": "The Death of Advertising – Member Feature Stories – Medium"
},
"type": "success"
}
The error I'm getting is newarticle is not defined.
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, ActivityIndicator, ListView, Text, View, Alert,Image, Platform } from 'react-native';
class App extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true
}
}
GetItem (flower_name) {
Alert.alert(flower_name);
}
componentDidMount() {
return fetch('https://reactnativecode.000webhostapp.com/FlowersList.php')
.then((response) => response.json())
.then((responseJson) => {
let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.setState({
isLoading: false,
dataSource: ds.cloneWithRows(responseJson),
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
ListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.MainContainer}>
<ListView
dataSource={this.state.dataSource}
renderSeparator= {this.ListViewItemSeparator}
renderRow={(rowData) =>
<View style={{flex:1, flexDirection: 'row'}}>
<Image source = {{ uri: rowData.flower_image_url }} style={styles.imageViewContainer} />
<Text onPress={this.GetItem.bind(this, rowData.flower_name)} style={styles.textViewContainer} >{rowData.flower_name}</Text>
</View>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
// Setting up View inside content in Vertically center.
justifyContent: 'center',
flex:1,
margin: 5,
paddingTop: (Platform.OS === 'ios') ? 20 : 0,
},
imageViewContainer: {
width: '50%',
height: 100 ,
margin: 10,
borderRadius : 10
},
textViewContainer: {
textAlignVertical:'center',
width:'50%',
padding:20
},
tabIcon: {
width: 16,
height: 16,
}
});
AppRegistry.registerComponent('App', () => App);
export default App;

React Native - Adding data to database not working

I'm wondering what is the proper way to this: Currently I have an "item/s" that comes from my database for display, from here I'm trying to send an "item/s" back to my database once a user taps the send button.
With this code, I'm having the following output:
Nodemon example:
console.log example:
Here's my code
export default class Dishes extends Component {
constructor(props) {
super (props)
this.state = {
data: [],
id: [],
price: [],
count: '',
SplOrder: '',
name: '',
menu_price: '',
tbl: this.props.navigation.state.params.tbl,
orderDet: this.props.navigation.state.params.orderDet,
}
}
submit = ({ item, index }) => {
fetch('http://192.168.254.102:3308/SendOrder/Send', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
order_no: this.state.orderDet,
tbl_id: this.state.tbl,
//special_request: this.state.SplOrder,
menu_desc: this.state.name, //item
menu_price: this.state.menu_price, //item
//order_quantity: this.state.count,
})
}).then(res => res.json())
.then((responseJson) => {
Alert.alert(JSON.stringify(responseJson))
console.log(responseJson);
})
.catch(error => console.error('Error:', error))
}
componentDidMount() {
this.fetchData();
}
_renderItem = ({ item, index }) => {
return (
<View>
<Text>Name: { name }</Text>
<Text>Price: ₱{ price }</Text>
<Text>Status: { item.menu_status }</Text>
</View>
)
}
render() {
return (
<View>
<FlatList
data = {this.state.data}
keyExtractor = {(item, index) => index.toString()}
extraData = {this.state}
renderItem = {this._renderItem} />
<View>
<TouchableOpacity
onPress = {(item) => this.submit(item)}>
<Text style = {styles.SendText}>Send Order</Text>
</TouchableOpacity>
</View>
</View>
)
}
}
UI sample:

Categories