How to use the response in fetch request React Native - javascript

I am new in react native world and (JS).
I want to send phone number and password to the server to login. I can send data and receive response, however, I don't how I should handle response. I have a function called _response_recognizer. But it is not working. Even setStat. All of the tutorials only say how to connect to server and how fetch data from it. What is the best approach to use response in my login form. If it's status is 200 I want to navigate another screen, else I want to toast a message.
import React, {Component} from 'react';
import {
Platform,
StyleSheet,
Text,
View,
TextInput, Button
} from 'react-native';
export default class LoginForm extends Component<{}> {
constructor(props) {
super(props);
this._onLogInPressed = this._onLogInPressed.bind(this);
this._response_recognizer = this._response_recognizer.bind(this);
this.state = {
phone_number: '',
password: '',
data: {}
};
}
_response_recognizer(data: string ){
}
_onLogInPressed = () => {
var data = {
'phone_number': this.state.phone_number,
'password': this.state.password
}
fetch("http://192.168.1.12:5000/login", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
}).then(function(response){
return response.json();
}).then(function(data){
console.log(data)
this._response_recognizer(data)
}) .catch((error) => {
console.log("Error" + error);
});
};
render() {
return (
<View style={styles.flow}>
<Text style={styles.text}>phone number:</Text>
<TextInput keyboardType='numeric'
style={styles.input}
ref="phone_number"
onChangeText={(phone_number) => this.setState({phone_number})}
maxLengt={11}
value={this.state.phone_number}
/>
<Text style={styles.text}>password:</Text>
<TextInput style={styles.input} secureTextEntry={true} ref="password"
onChangeText={(password) => this.setState({password})}
value={this.state.password}/>
<Button style={styles.button} onPress={this._onLogInPressed} title='login'/>
</View>
);
}
}

Two things.
Your _response_recognizer function is requesting data: string but you are returning an json object:
.then(function(response){
return response.json();
}).then(function(data){
console.log(data)
this._response_recognizer(data)
})
Change that to data: object.
Secondly, you are using function declarations (function(){}) in your .then's. Without directly binding this, you lose the scope your Class functions. Change them to an arrow function (() => {}) to fix the scope issue:
.then((response) => response.json())
.then((data) => {
console.log(data)
this._response_recognizer(data)
})
You can also opt to remove one of the .then operations:
.then((response) => {
console.log(response.json())
this._response_recognizer(response.json())
})
✌🏾

check this ...
i hope this code helps you
export default class LoginForm extends Component<{}> {
state = {
data:[],
}
_onLogInPressed = () => {
fetch('http://192.168.1.12:5000/login',{
method:'POST',
headers:{
'Accept':'application/json',
'Content-Type':'application/json',
},
body:JSON.stringify({
'phone_number': this.state.phone_number,
'password': this.state.password
})
})
.then((response) => response.json())
.then((res) =>{
if(res.success === true){
alert(res.response);
let datadata = res.data;
this.setState({data:datadata})
} else {
alert(res.response);
}
})
.done();
};
//// Render function
////Rander function
}

Related

400 BAD REQUEST when POST using Axios in React

Can any help me with this?
I keep getting a 400 bad request from Axios.
I can pass a GET request and confirm its working fine.
I create http-common.js file with following code:
import axios from 'axios';
export default axios.create({
baseURL: 'https://5fa97367c9b4e90016e6a7ec.mockapi.io/api',
headers: {
'Content-type': 'application/json'
}
});
Then,I create a service that uses axios object above to send HTTP requests.
TodoService.js
import http from '../http-common/http-common';
const getAll=()=>{
return http.get('/todos');
};
const get=id=>{
return http.get(`/todos/${id}`);
};
const create=data=> {
return http.post('/todos',data);
};
const update=(id,data)=>{
return http.put(`/todos/${id}`,data);
};
const remove = id => {
return http.delete(`/todos/${id}`);
};
const removeAll = () => {
return http.delete(`/todos`);
};
const findByTitle = title => {
return http.get(`/todos?title=${title}`);
};
export default {getAll,get,create,update,remove,removeAll,findByTitle};
Then, I use TodoDataService.create(data) ... in AddTodos component.
AddTodos.js
import React, { useState } from 'react';
import TodoDataService from '../services/TodoService';
const AddTodos = () => {
const initialTodoState={
id:null,
title: '',
isDone: false,
user: ''
};
const [todo,setTodo]=useState(initialTodoState);
const [submitted,setSubmitted]=useState(false);
const handleInputChange=event=>{
const {name,value}=event.target;
setTodo({...todo,[name]:value});
};
const saveTodo =()=>{
var data={
title: todo.title,
isDone:todo.isDone,
user: todo.user
};
console.log(data);
TodoDataService.create(data)
.then(response => {
setTodo({
id:response.data.id,
title: response.data.title,
isDone: response.data.isDone,
user: response.data.user
});
setSubmitted(true);
console.log(response.data);
})
.catch(e => {
console.log(e);
});
};
const newTodo=()=>{
setTodo(initialTodoState);
setSubmitted(false);
};
return (
<div className="submit-form">
{submitted ? (
<div> //...
) : (
<div>
<div className="form-group"> //... </div>
<div className="form-group"> //... </div>
<button onClick={saveTodo} className="btn btn-success">
Submit
</button>
</div>
)}
</div>
)
}
export default AddTodos;
When clicked Submit it's giving this error:
I recreate your api call and got this response:
await fetch('https://5fa97367c9b4e90016e6a7ec.mockapi.io/api/todos', {
method: 'POST', body: JSON.stringify({id: "123",title: "homework", isDone: false, user: "foo"})})
.then(response => response.json())
.then(data => {
console.log(data)
})
error 400 "Max number of elements reached for this resource!"
you need to delete some records in order to insert new ones
so after deleting a record:
await fetch('https://5fa97367c9b4e90016e6a7ec.mockapi.io/api/todos/1', {
method: 'DELETE'})
.then(response => response.json())
.then(data => {
console.log(data)
})
VM623:5 {id: "1", title: "deneme", isDone: true, user: "cafererensimsek"}
and posting a new one, now it works

React not re-rendering when setState following API calls

I have been struggling to understand what is going wrong with this simple todo list front end React app, which should interact with an express API.
my React code is:
import React, {Component} from 'react';
class App extends Component {
constructor(){
super();
this.state = {
todos:[],
currentItem: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleADDButton = this.handleADDButton.bind(this);
this.deleteItem = this.deleteItem.bind(this);
this.updateTodo = this.updateTodo.bind(this);
}
componentDidMount(){
fetch('http://ec2-x-xx-xx-xxx.eu-west-2.compute.amazonaws.com:3001/list')
.then(res => res.json())
.then((todosList) =>
{this.setState({'todos': todosList});
});
}
handleChange(event){
this.setState({currentItem: event.target.value});
}
handleADDButton(event){
fetch('http://ec2-x-xx-xx-xxx.eu-west-2.compute.amazonaws.com:3001/post', {
method: 'POST',
headers:{'Content-type': 'application/json'},
body: JSON.stringify({title: this.state.currentItem})
});
}
deleteItem(x){
fetch('http://ec2-x-xx-xx-xxx.eu-west-2.compute.amazonaws.com:3001/' + x, {
method: 'DELETE',
headers:{'Content-type': 'application/json'}
})
}
updateTodo(y){
fetch('http://ec2-x-xx-xx-xxx.eu-west-2.compute.amazonaws.com:3001/' + y, {
method: 'PUT',
headers:{'Content-type': 'application/json'},
body: JSON.stringify({title: this.state.currentItem})
})
}
render() {
return(
<div>
<h1> Todo List </h1>
<ul>
{this.state.todos.map((todo) => <li> {todo.title}
<button type="button" onClick={() => this.deleteItem(todo.key)} >x</button>
<button type="button" onClick={() => this.updateTodo(todo.key)}>update</button> </li>)}
</ul>
<input type="text" value={this.state.currentItem} onChange={this.handleChange} />
<button type="submit" onClick={this.handleADDButton}>ADD</button>
</div>
)
}
}
export default App
The calls do update the API, and if I manually refresh the page, the React app picks up on the new data coming through from the API. However, when clicking the buttons it doesn't re-render by itself.
Say for example I click the ADD Button. It sends an OPTIONS to which I get back a 200 code, a POST which also comes back with a 200 and only sometimes, a GET with a 200. There is no pattern in when it performs the last GET call and also there is no pattern in when it re-renders following a button click. To obtain the latest data I always have to refresh.
Don't know what to make of this and have been stuck for days.
I think there is no state update on button actions
try to add a state updates for the actions same as componentDidMount
For ex:
handleADDButton(event){
event.preventDefault();
fetch('http://ec2-x-xx-xx-xxx.eu-west-2.compute.amazonaws.com:3001/post', {
method: 'POST',
headers:{'Content-type': 'application/json'},
body: JSON.stringify({title: this.state.currentItem})
}).then(res => res.json())
.then((data) => {
this.setState((prevState) {
const todos = [...prevState.todos, data.todo];
return {
todos: todos
}
})
});
}
In this case you have to return the new todo which will catch in data.todo
And for delete action
deleteItem(x){
fetch('http://ec2-x-xx-xx-xxx.eu-west-2.compute.amazonaws.com:3001/' + x, {
method: 'DELETE',
headers:{'Content-type': 'application/json'}
}).then(res => res.json())
.then((data) => {
this.setState((prevState) {
const newTodos = prevState.todos.filter(t => t.key !== x);
return {
todos: newTodos
};
})
});
}
These codes are not tested.
actually you don't have any state update in your code. you have to use "setState" when fetching data from API. I recommended learning arrow function and Hooks and use somethings like AXIOS to manage API calls.

Reach router refresh page

Setup:
I have a form that send data to an action creator, which in turn submits to an API and gets the result. What I want is when the form submits successfully, to refresh the form with blank inputs.
This is how the component looks like
import React, { Component } from "react";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
import { addNewProduct } from "../../redux/actions";
class Admin extends Component {
state = {
ProductName: ""
};
onChange = e => {
e.preventDefault()
this.setState({
[e.target.name]: e.target.value
})
}
handleProductSubmit = (event) => {
event.preventDefault();
this.props.addNewProduct(
this.state.ProductName,
);
}
render() {
return (
<div>
{/* Form ends */}
<form onSubmit={this.handleProductSubmit} autoComplete="off">
<input
type="text"
value={this.state.ProductName}
name="ProductName"
onChange={this.onChange}
/>
<button type="submit" className="btn btn-dark">
Upload Product
</button>
</form>
{/* Form Ends */}
</div>
);
}
}
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({ addNewProduct, createNewLogin }, dispatch);
};
export default connect(null, mapDispatchToProps)(Admin);
This is the result of the console.log(this.props)
location: Object { pathname: "/Home/admin", href: "http://localhost:3000/Home/admin", origin: "http://localhost:3000", … }
navigate: navigate(to, options)
​​
length: 2
​​
name: "navigate"
​​
prototype: Object { … }
​​
<prototype>: ()
This is how the actionCreator looks like
export const addNewProduct = (ProductName, ProductCategory, ProductImg) => (dispatch) => {
const productData = new FormData();
productData.append("ProductName", ProductName)
axios.post("http://localhost:4500/products/", productData,
{
headers: {
"Content-Type": "multipart/form-data",
"Authorization": localStorage.getItem("Authorization")
}
})
.then(res => {
console.log(res.data)
setTimeout(() => {
console.log("doing the timeout")
navigate("/Home/admin")}, 1500);
})
.catch(err =>
console.log(`The error we're getting from the backend--->${err}`))
};
Current behavior
When I submit the form and the API return 201, the page does not refresh and the inputs do not go blank
Expected behavior:
When I get a 201 from the API, the page should refresh and the inputs should be blank.
Please help me how to achieve this.
Using navigate to move the same url or page won't remount the page and reset your field values.
Its better is you actually return a promise from your action creator and reset the state yourself
export const addNewProduct = (ProductName, ProductCategory, ProductImg) => (dispatch) => {
const productData = new FormData();
productData.append("ProductName", ProductName)
return axios.post("http://localhost:4500/products/", productData,
{
headers: {
"Content-Type": "multipart/form-data",
"Authorization": localStorage.getItem("Authorization")
}
})
.then(res => {
console.log(res.data)
})
.catch(err =>
console.log(`The error we're getting from the backend--->${err}`))
};
In the component
handleProductSubmit = (event) => {
event.preventDefault();
this.props.addNewProduct(
this.state.ProductName,
).then(() => {
this.setState({ProductName: ""})
});
}

how post props redux React

I would like to explain my problem of the day.
I can't post "this.props.total",
I do not understand how to post a props, can you help me pls?
currently the props works correctly.
import React, { Component } from 'react';
import { CardText, } from 'reactstrap';
import { connect } from 'react-redux'
class thisPropsFortotal extends Component {
handleSubmit = (e) => {
e.preventDefault();
const config = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({this.props.total}),
};
const url = entrypoint + "/alluserpls";
fetch(url, config)
.then(res => res.json())
.then(res => {
if (res.error) {
alert(res.error);
} else {
alert(`ajouté avec l'ID ${res}!`);
}
}).catch(e => {
console.error(e);
}).finally(() => this.setState({ redirect: true }));
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<button type="submit">Add</button>
</form>
<CardText>{this.props.total} € </CardText>
</div>
);
}
}
const mapStateToProps = (state) => {
return {
total: state.addedItems.reduce((acc, item) => { return acc + (item.quantity *
item.price) }, 0)
//addedItems: state.addedItems
}
}
export default connect(mapStateToProps)(thisPropsFortotal)
Do you have an idea of how to fix this? Neff
You are attempting to stringify {this.props.total}, which is invalid syntax.
You can pass an object explicitely defining the total property like so:
body: JSON.stringify({total: this.props.total}),
Or, simply stringify the this.props object itself:
body: JSON.stringify(this.props),

setState() not mutating state immediately

I have a parent component that uses a get request to retrieve a JWT Token and then passes that token as a prop down to a child component. That token gets passed in another get request to authorize and retrieve data. On the method that does that get request, I am using setState after the request is successful to update the state of an empty array. The problem is that it is lagging behind due to setState not mutating the state quickly enough and the array is staying empty. I am trying to pass that array value as a prop to a child component. Any help is appreciated.
App.js - Parent Component
class App extends Component {
constructor(props) {
super(props);
this.state = {
token: '',
};
this.getToken = this.getToken.bind(this);
}
getToken() {
fetch('https://login-cmhmanagement.itg.cct-pubweb.com/nofapsaml', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json; charset=utf-8',
},
})
.then(response => response.json())
.then(data => {
this.setState({ token: data });
});
}
componentDidMount() {
this.getToken();
}
render() {
const { token } = this.state;
return (
<div className="app-container">
<Navigation
token={token}
/>
</div>
);
}
Navigation.Js
export default class Navigation extends Component {
constructor(props) {
super(props);
this.state = {
user: [],
value: '',
};
this.getUserData = this.getUserData.bind(this);
}
componentDidMount() {
setTimeout(() => {
this.getUserData();
}, 2000);
}
getUserData() {
const { token } = this.props;
let auth = token;
fetch(url, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${auth}`,
},
})
.then(response => response.json())
.then(result => {
this.setState({ user: result });
});
}
render() {
const { user } = this.state;
return (
<SideBarStyled>
<UserInfo
authorizedLots={user.authorizeLots}
/>
</SideBarStyled>
);
}
You should never rely on timeout, because you never know the network latency.
Rather use like below :-
export default class Navigation extends Component {
constructor(props) {
super(props);
this.state = {
user: [],
value: '',
};
this.getUserData = this.getUserData.bind(this);
}
componentDidUpdate(prevProps) {
if(prevProps.token !== this.props.token){
this.getUserData();
}
}
getUserData() {
const { token } = this.props;
let auth = token;
fetch(url, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${auth}`,
},
})
.then(response => response.json())
.then(result => {
this.setState({ user: result });
});
}
render() {
const { user } = this.state;
return (
<SideBarStyled>
<UserInfo
authorizedLots={user.authorizeLots}
/>
</SideBarStyled>
);
}

Categories

Resources