How to set headers in axios, ReactNative - react-native

i build an application, React Native as Frontend and Django as Backend,
i use axios to take data from user then send it to backend it show error Request failed with status code 400
i have used Restful API that build with django and run the server locally,
so i think when i add headers to axios then the API request response without errors
so,How to set headers in axios
the user enter the data through form and send it to the backend
Add.js page with form take data from user send it to the backend
import * as React from "react";
import {View, Text, Image, StyleSheet, Button, TextInput} from "react-native";
import { COLORS, SIZES,FONTS} from '../styles/theme.js';
import { FieldArray, Formik} from "formik";
import axios from 'axios';
const AddScreen =()=>{
const radioopt = [{},{},{},{}];
const submit = (val) => {
if(val.type == "" || val.category == "" || val.amount == ""){
alert("Please Enter all details");
return;
}
// 'http://192.168.8.143:8000/transactions/'
axios.post('http://192.168.8.143:8000/transactions/', {
"id": "1",
"type": val?.type,
"category": val.category,
"amount": val?.amount,
// "owner" : "",
"date" : Date.now(),
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
return(
<View style={{flex: 1, backgroundColor:COLORS.gray}}>
<Formik
initialValues={{type:'',category:'', amount:''}}
onSubmit={(values)=>{submit(values)}}
>
{(props)=>(
<View style={styles.whitecard}>
<TextInput
style={styles.inputstyle}
placeholder='type'
onChangeText={props.handleChange('type')}
value={props.values.type}
/>
<TextInput
style={styles.inputstyle}
placeholder='category'
onChangeText={props.handleChange('category')}
value={props.values.category}
/>
<TextInput
style={styles.inputstyle}
placeholder='amount'
onChangeText={props.handleChange('amount')}
value={props.values.amount}
keyboardType='numeric'
/>
<View style={{margin:10,padding:0, backgroundColor:COLORS.pink, borderRadius:6}}>
<Button title='Submit' color='white' onPress={props.handleSubmit}></Button>
</View>
</View>
)}
</Formik>
</View>
);
}
...
export default AddScreen;

You must pass an object with headers like documentation says: https://axios-http.com/docs/req_config
so your request will be:
axios.post('http://192.168.8.143:8000/transactions/',{formData}, {
//example with bearer token
headers: {
'Authentication': 'Bearer 89324u2jhjwe98'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});

You can pass options on third argument. There you can add headers on post method like following:
axios.post('https://example.com', formData, { headers: 'content-type': 'text/json',...otherHeaders })

Related

React Native token issue when submit

i build an application with reactNative and Expo for front-end and django for back-end
i want take token from AsyncStorage to recognised the user, but the is an errors
Warning: An unhandled error was caught from submitForm(), [ReferenceError: Can't find variable: useState]
when i change the owner id to static value the submit works fine and show the token value on the console log not sure where is the issue exactly
import React, {useState} from 'react';
import { FieldArray, Formik } from "formik";
import axios from "axios";
import AsyncStorage from '#react-native-async-storage/async-storage';
import jwt_decode from "jwt-decode";
function AddScreen(props){
const submit = ({ type, category, amount }) => {
//here you define the token to be set
const [token, setToken] = useState();
//here you get the token from AsyncStorage
const getToken = async () => {
try {
const data = await AsyncStorage.getItem('token');
if (data !== null) {
setToken(data)
return data;
}
} catch (error) {
console.log(error);
}
};
//here you set the token
getToken()
//here you decode the token
const tokens = token;
const decoded = jwtDecode(tokens);
//here you get the id and it returns a number
const id = decoded.user_id
const config = {
headers: {
"Content-Type": "application/json",
},
};
const date = Date.now();
const owner = id;
const body = JSON.stringify({ type, category, amount, date, owner });
if (type == "" || category == "" || amount == "") {
alert("Please Enter all details");
return;
}
// 'http://192.168.8.143:8000/transactions/'
axios
.post("http://192.168.8.143:8000/transactions/", body, config)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
};
return (
<View style={{ flex: 1, backgroundColor: COLORS.gray }}>
<Formik
initialValues={{ type: "", category: "", amount: "" }}
onSubmit={(values) => {
submit(values);
}}
>
{(props) => (
<View style={styles.whitecard}>
<TextInput
style={styles.inputstyle}
placeholder="type"
onChangeText={props.handleChange("type")}
value={props.values.type}
/>
<TextInput
style={styles.inputstyle}
placeholder="category"
onChangeText={props.handleChange("category")}
value={props.values.category}
/>
<TextInput
style={styles.inputstyle}
placeholder="amount"
onChangeText={props.handleChange("amount")}
value={props.values.amount}
keyboardType="numeric"
/>
<View
style={{
margin: 10,
padding: 0,
backgroundColor: COLORS.pink,
borderRadius: 6,
}}
>
<Button
title="Submit"
color="white"
onPress={props.handleSubmit}
></Button>
</View>
</View>
)}
</Formik>
</View>
);
};
...
export default AddScreen;
the error show
Warning: An unhandled error was caught from submitForm(), [Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.]
You are not importing UseState from React. Also you need to convert your code into a react functional component.
EDIT
For your new error, you need to move the useState out of submit. It must be at the root level of the functional component. I am updating the code example below as well.
import React, {useState} from 'react';
//All your other imports
function AddScreen(props) {
const [token, setToken] = useState(null);
//Everything else remains same inside
};

How to store API response in state And pass this response value to another screen as params in react native

I am new to react native. I have created A screen. Where I am getting response from API. but now I want to store that response in state. and I want to send that value to another screen by navigation params.
my response is like this ->
Array [
Object {
"phpid": 10,
},
]
here is my code
constructor(props) {
super(props);
this.state={
};
}
fetch('https://xuz.tech/Android_API_CI/uploaddata/t_details?query=', {
method: 'POST',
headers: {'Accept': 'application/json, text/plain, */*', "Content-Type": "application/json" },
body: JSON.stringify([{"==some values=="}])
})
.then((returnValue) => returnValue.json())
.then(function(response) {
console.log(response)
return response.json();
render(){
return (
<View style={{flex: 1}}>
color="black" onPress={() => this.props.navigation.navigate("FormItems",{i want to send value to formitems})} />
</View>
)}
Set your state once you receive your response, then use your state as params when navigating. Once your fetch has been resolved:
this.setState({ response: response.json() });
Sending params to another screen is fairly simple, you just need to pass an object as the second parameter to navigate.
this.props.navigation.navigate('FormItems', {
form: this.state.response,
});
The receiving component will then need to read those params:
class DetailsScreen extends React.Component {
render() {
const { navigation } = this.props;
return (
<Text>{JSON.stringify(navigation.getParam('form', 'some default'))}</Text>
}
}
A full explanation on how to use params with react-navigation v4 can be found here: https://reactnavigation.org/docs/4.x/params
Use it like this. first initialise the state and when you get data from api set the data in state and when button press pass the data to new screen in params.
import React, { Component } from 'react';
import { Text, View } from 'react-native';
export default class Example extends Component {
state = {
data: [], // initialize empty state
};
componentWillMount() {
this.requestData();
}
requestData = () =>{
fetch('https://xuz.tech/Android_API_CI/uploaddata/t_details?query=', {
method: 'POST',
headers: {'Accept': 'application/json, text/plain, */*', "Content-Type": "application/json" },
body: JSON.stringify([{"==some values=="}])
})
.then((returnValue) => returnValue.json())
.then(function(response) {
this.setState({
data:response //set data in state here
})
})
}
render() {
return (
<View style={{ flex: 1 }}>
<Button
color="black"
onPress={() =>
this.props.navigation.navigate('FormItems', {
data: this.state.data, // pass data to second screen
})
}
/>
</View>
);
}
}

Csrf token post in React Native

I've made a website using Node and Express as a framework. Now we are shifting to a React Native Mobile Application. While making the login page I have made a post request as given below
index.js
import React, { Component } from 'react'
import {
View,
TextInput,
Text,
Button,
Alert,
} from 'react-native';
import styles from './styles'
class Home extends Component {
constructor(props){
super(props)
state = {email: "", password: ""}
}
checkLogin(){
const { email, password } = this.state;
if(email ==="admin" || password === "admin" || true){
fetch('http://localhost:3021/user/signin', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email,
password: password,
}),
})
.then((response) => {
console.log(response)
})
.catch((error) => {
console.error(error);
})
}
else{
Alert.alert('Error', 'Email/Password mismatch', [{
text: 'Okay',
}])
}
}
render(){
const {heading, input, parent} = styles
return (
<View style={parent}>
<Text style={heading}> Login into the Application </Text>
<TextInput style={input} placeholder="Email" onChangeText={text => this.setState({email: text})} underlineColorAndroid='black'/>
<TextInput style={input} secureTextEntry={true} placeholder="Password" onChangeText={text => this.setState({password: text})} underlineColorAndroid='black'/>
<Button title={"Login"} onPress = {() => this.checkLogin()} />
</View>
);
}
}
export default Home
When I sent this request, I got no response and checked it on Postman for the response and it was coming as an invalid csrf token and 403 error. Initially in my web app while logging in, the form consisted of a CSRF token which was passed as given below:
<input type = "hidden" name="_csrf" value="{{ csrfToken }}">
How do I replicate this on the React Native App? I tried searching online, however, could not find any such method discussed.
You can
1. Either add CSRF token in the request headers
OR 2. Disable CSRF on in your back-end.
export const login = (user) => {
fetch('http://localhost:3000/api/session', {
method: 'POST',
credentials: 'include',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-TOKEN': token
},
body: JSON.stringify({user})
})
// promise handling
}

How do I get this handleSubmit on a Formik form to perform a Post request

My handleSubmit function on a Formik form is not properly sending a Post request to my backend API. I believe I have the code 97% of the way there, but don't quite understand the nuances of what is missing.
The form has an email field, and I need the Submit to pass that email string to a POST request. The code below has 4 files at play: Enter-Email.js, SessionStore.js, UserService.js and request.js.
I believe most of the problem is in my handleSubmit function in Enter-Email.js and my #action sendResetCode in SessionStore.js.
Thanks for any assistance.
Enter-Email.js:
import React, { Component, Fragment } from "react";
import { observer } from "mobx-react/native";
import { Formik } from "formik";
import * as yup from "yup";
#observer
class EnterEmail extends Component {
handleSubmit = async ({ <----- function I think has the problem
email,
values,
}) => {
const {
navigation: { navigate },
sessionStore: { sendResetCode }
} = this.props;
let response = await sendResetCode({ <------ the function to make the POST request!
email: email
});
if (response) {
return navigate("VerificationCode", { values });
} else {
return Alert(
{ message: "Error sending the reset link" },
"There was an error sending the reset link. Please try again."
);
}
}
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<Text>Enter your e-mail to receive a link to reset your password</Text>
<Formik
initialValues={{ email: ''}}
onSubmit={this.handleSubmit}
validationSchema={yup.object().shape({
email: yup
.string()
.email()
.required(),
})}
>
{({ values, handleChange, setFieldTouched, handleSubmit }) => (
<Fragment>
<View>
<View>
<TextInputGroup
id="email"
keyboardType="email-address"
label="Email"
onBlur={() => setFieldTouched("email")}
value={values.email}
onChangeText={handleChange("email")}
/>
</View>
</View>
<View>
<LargeButton
text="Send Reset Link"
onPress={handleSubmit}
/>
</View>
</Fragment>
)}
</Formik>
</SafeAreaView>
);
}
}
export default EnterEmail;
SessionStore.js:
#action sendResetCode = async (emailField: Object): Promise<void> => {
let res = await userService.sendResetCode(emailField);
// if it fails, return res.success to trigger error on enter-email.js
if (!res.success) {
return res.success;
}
};
UserService.js:
// to send code to email that was entered:
userService.sendResetCode = async (
body: Object
): Promise<ApiResponse<Nurse>> => {
const response: Response = await request.post(
`/v1/password_resets`, <---- backend endpoint which works
body
);
return handleResponse(response);
};
request.js:
post(url, body, useBody) {
return fetch(this._buildUrl(url), {
method: "POST",
headers: getCommonHeaders(useBody),
body: useBody ? body : JSON.stringify(body)
});
},
In case it matters, here is the versions in Package.json:
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
"native-base": "^2.12.1",
"react": "16.8.0",
"react-navigation": "^3.11.0",
"formik": "^1.5.8",
"mobx": "5.9.4",
"mobx-react": "5.4.4",

Why isn't mailchimp API working with fetch?

I'm trying to add an email address to a mailchimp list I have.
This is for a react native app and I'm trying to implement the request using fetch.
This is my code within the component:
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { connect } from 'react-redux';
import { emailChanged, nameChanged, addToWaitingList } from '../actions';
import { Card, CardSection, Input, Button, Spinner } from '../components/Auth';
class addToWaitingListForm extends Component {
onEmailChange(text) {
this.props.emailChanged(text);
}
onButtonPress() {
const { email } = this.props;
this.props.addToWaitingList({ email });
}
renderButton() {
if (this.props.loading) {
return <Spinner size="large" />;
}
return (
<Button onPress={this.onButtonPress.bind(this)}>
Keep me in the loop!
</Button>
);
}
render() {
return (
<View>
<Card>
<CardSection>
<Input
placeholder="your name"
onChangeText={this.onNameChange.bind(this)}
value={this.props.name}
/>
</CardSection>
<CardSection>
<Input
placeholder="email#uni.ac.uk"
onChangeText={this.onEmailChange.bind(this)}
value={this.props.email}
/>
</CardSection>
<Text style={styles.errorTextStyle}>
{this.props.error}
</Text>
<CardSection style={{ borderBottomWidth: 0 }}>
{this.renderButton()}
</CardSection>
</Card>
</View>
);
}
}
const mapStateToProps = ({ auth }) => {
const { email, name, error, loading } = auth;
return { email, name, error, loading };
};
export default connect(mapStateToProps, {
emailChanged,
addToWaitingList
})(addToWaitingListForm);
Add this is my action code for interacting with the mailchimp api:
import Router from '../../navigation/Router';
import { getNavigationContext } from '../../navigation/NavigationContext';
export const addToWaitingList = ({ email }) => {
const emailListID = 'e100c8fe03';
fetch(`https://us13.api.mailchimp.com/3.0/lists/${emailListID}/members/`, {
method: 'POST',
body: JSON.stringify({
'email_address': email,
'status': 'subscribed',
'merge_fields': {
'FNAME': 'Urist',
'LNAME': 'McVankab'
}
})
})
.then(() => addSubscriberSuccess())
.catch(error => console.log(error));
};
const addSubscriberSuccess = () => {
getNavigationContext().getNavigator('root').immediatelyResetStack([Router.getRoute('auth')]);
};
Right now, the error I'm just getting back is ExceptionsManager.js:62 Cannot read property 'type' of undefined and Error: unsupported BodyInit type
What does this mean and how can I fix this?
You need to do two things.
First off you need to send the basic authentication via fetch so you cant do "user:pass" You have to convert it with btoa('user:pass').
Then you have to send it with mode: 'no-cors'
let authenticationString = btoa('randomstring:ap-keyxxxxxxx-us9');
authenticationString = "Basic " + authenticationString;
fetch('https://us9.api.mailchimp.com/3.0/lists/111111/members', {
mode: 'no-cors',
method: 'POST',
headers: {
'authorization': authenticationString,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
email_address: "dude#gmail.com",
status: "subscribed",
})
}).then(function(e){
console.log("fetch finished")
}).catch(function(e){
console.log("fetch error");
})