I am trying to fetch data, set state and change route in componentDidMount, but it can not be done(only after clicking on the screen ). I guess there something has to do with asynchronous nature of fetch but how can it be fixed?
componentDidMount(){
AsyncStorage.multiGet([USER_TOKEN, USER_REFRESH_TOKEN,USER_REMEMBERED]).then((data) => {
const userRemembered = JSON.parse(data[2][1])
const userAccessToken = data[0][1]
const userRefreshToken = data[1][1]
if (userRemembered) {
fetch("SOME_URL", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
refreshToken: userRefreshToken
})
})
.then(response => response.json())
.then(responseData => {
console.log(responseData); // only after clicking on the screen it is logged
if (responseData.success) {
AsyncStorage.multiSet([[USER_TOKEN,responseData.response.accessToken],[USER_REFRESH_TOKEN,responseData.response.refreshToken],[USER_REMEMBERED,JSON.stringify(true)]])
this.setState({
token:responseData.response.accessToken,
refreshToken: responseData.response.refreshToken,
isLoggedIn: true
}) //only after clicking on the screen state is changed
this.changeRoute(this.state) //only after clicking on the clicking on the screen route is changed
}
else {
console.log("API is not responding");
}
})
.catch((error) => {
console.log(error)
})
}
else{
console.log('user has not checked Remember Me');
}
})
}
I finally figured it out. I had Remote JS Debugging turned on and it was messing things up. I turned it off and everything works fine.
Related
I am trying to create a web app that uploads file and attached the current user to the file model as a foreign key. For some reason the get request is being wiped, but it does initially get the needed information.
handleSubmit = (e) => {
e.preventDefault();
axios.get('http://127.0.0.1:8000/core/current_user/', {
headers: {
Authorization: `JWT ${localStorage.getItem('token')}`,
}
}).then((user) => {
this.state.creator = user.data;
console.log(this.state.creator);
})
console.log(this.state.creator);
let form_data = new FormData();
form_data.append('creator', this.state.creator);
form_data.append('file', this.state.file);
form_data.append('title', this.state.title);
form_data.append('description', this.state.description);
axios.post('http://localhost:8000/core/posts/', form_data, {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: `JWT ${localStorage.getItem('token')}`,
}
}).then(res => {
console.log(res.data);
}).catch(err => console.log(err))
};
The 1st console is returning the user information but the 2nd console returns null. Any help will be really appreciated.
Your then statement after the original get ends on line 11, and the rest of your code is outside of that.
With asynchronous code, the code outside of the then block will continue running while it's waiting for a response, so this.state.creator will not have been set yet. Then it will return to the code inside the then block once the promise resolves.
You need to move all of the second block of code inside the intial then block so it is only executed once a response to the original get request has returned:
handleSubmit = (e) => {
e.preventDefault();
axios
.get('http://127.0.0.1:8000/core/current_user/', {
headers: {
Authorization: `JWT ${localStorage.getItem('token')}`,
},
})
.then((user) => {
this.state.creator = user.data;
console.log(this.state.creator);
let form_data = new FormData();
form_data.append('creator', this.state.creator);
form_data.append('file', this.state.file);
form_data.append('title', this.state.title);
form_data.append('description', this.state.description);
axios
.post('http://localhost:8000/core/posts/', form_data, {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: `JWT ${localStorage.getItem('token')}`,
},
})
.then((res) => {
console.log(res.data);
})
.catch((err) => console.log(err));
});
};
I have a sweetalert update component, which update certain information and than redirect user to a different route if updation of data results in success. Everything works fine but the problem is on redirection through useHistory() the component where user is redirected do no update the changes made in the data.
Here is my update component code which update the data on submit event
const submitHandler = (e) => {
e.preventDefault();
// Fire confirmation
Swal.fire({
title: 'Are you sure?',
showDenyButton: true,
showCancelButton: true,
confirmButtonText: `Yes`,
denyButtonText: `No`,
}).then((result) => {
if (result.isConfirmed) {
updateNotes();
history.push('/notes');
} else if (result.isDenied) {
Swal.fire('Notes not updated!', '', 'info');
}
});
};
var bodyFormData = new FormData();
async function updateNotes() {
bodyFormData.append('description', notesData.description);
const requestOptions = {
method: 'PUT',
headers: { Authorization: AuthStr },
body: bodyFormData,
};
fetch(URL, requestOptions)
.then(async (response) => {
const data = await response.json();
// check for error response
if (!response.ok) {
const error = (data && data.message) || response.status;
return Promise.reject(error);
}
Swal.fire('Notes updated successfully', '', 'success');
})
.catch((error) => {
Swal.fire('Error updating notes', '', 'error');
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
And here is my notes component where the user is redirected, This component fetch when component loads
// fetch notes
useEffect(() => {
axios
.get(fetchURL, { headers: { Authorization: AuthStr } })
.then((response) => {
// If request is good...
if (response) {
if (!response.data[response.data.length - 1].has_next) setNext(0);
setNotes(response.data);
}
})
.catch((error) => {
toast.error('Something went wrong, please refresh');
console.log(error);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [fetchURL]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
In short i want to run this fetch method everytime component renders or fetchURL state modifies.
Please suggest a possible solution.
I want to show an alert message when user login fails.But alert is not showing.Following is my code in react native.
login
onPressLogin(){
fetch('http://192.168.1.10:3000/users/login',{
method: 'POST',
headers:{
'Content-Type' : 'application/json',
'Accept':'application/json'
},
body: JSON.stringify({
contact:this.state.contact,
password: this.state.password,
})
})
.then(response => response.json())
.then((responseData) =>
{
this.setState({
userdetail: responseData,
})
if(responseData){
setTimeout(() => {
Actions.firstScreen();
}, 2300);
AsyncStorage.saveItem('userid', this.state.userData.phone_no);
} else {
console.log(responseData);
Alert(responseData);
}
});
}
What I'm getting now is it will redirect to firstScreen on successful login but it alert is not coming on unsuccessful login.When I consoled I'm getting unexpected end of json input error but I'm using node js as backend the error result is showing there following is my code in nodejs
else {
appData.error= 1;
appData["data"] = "Phone number and Password does not match";
res.status(204).json(appData);
console.log(appData);
}
}else{
appData.error=1;
appData["data"] ="Phone number does not exist";
res.status(204).json(appData);
console.log(appData);
}
the consoled result of appData is
{ error: 1, data: 'Phone number does not exist' }
I don't know the reason why this error message is not showing within responseData in react native.
onPressLogin(){
fetch('http://192.168.1.10:3000/users/login',{
method: 'POST',
headers:{
'Content-Type' : 'application/json',
'Accept':'application/json'
},
body: JSON.stringify({
contact:this.state.contact,
password: this.state.password,
})
})
.then(response => response.json())
.then((responseData) =>{
if(responseData.error !== 1){ // verify the success case, as you didn't provide the success case i am using the error code
this.setState({ // its recommended you verify the json before setting it to state.
userdetail: responseData,
})
setTimeout(() => {
Actions.firstScreen();
}, 2300);
AsyncStorage.setItem('userid', this.state.userData.phone_no); // its setItem not saveitem.
} else {
console.log(responseData);
Alert.alert(JSON.stringify(responseData)); // Alerts doesn't allow arrays or JSONs, so stringify them to view in Alerts
}
}).catch((error) => {
// handle catch
console.log("error:"+JSON.stringify(error));
});
}
Always use 'catch' at the end of promises and handle them.
Do let me know if you still face the issue.
I used two classes
I call the second class as below
let s = new SearchExtend();
output = s.fetchData(search)
alert(output)
The second function:
fetchData = (search) => {
fetch('http://example.com/search.php' , {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
// Getting the search.
search: search
})
}).then((response) => response.json())
.then((responseJson) => {
return responseJson;
})
.catch((error) => {
console.error(error);
});
}
But i get in "alert" undefined
When I use this.setState instead of return, I get the following error:
warning setstate(...) can only update a mounted or mounting component
You are getting undefined because you are using promises. Initially it returns undefined and once promise is resolved you get the actually data.
A better way to handle this would be to return the promise and resolve it externally as follows:-
const fetchApi = () => {
return fetch("https://swapi.co/api/people" , {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
}).then((response) => {
return response.json();
})
.then((responseJson) => {
return responseJson;
})
.catch((error) => {
console.error(JSON.stringify(error));
});
}
fetchApi()
.then((data) => {
console.log("data", data);
})
I am creating an app in React Native and have bumped in to some major issues with fetching data from my server and using it in my program.
My architechture differs a bit from the example provided by React Native in their documentation, but I have tried a bunch of different ways. The token is correct and I am obviously calling the method in a sense correctly, but it does not return the data to the other side of my program.
In Methods.js
exports.loginUser = function(TOKEN) {
fetch(baseUrl + 'login' , {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
accessToken: TOKEN,
},)
})
.then((response) => response.text())
.then((responseText) => {
console.log(typeof responseText);
return responseText
})
.catch((error) => {
console.warn(error);
});
};
Where it logs the type of the data as a string, and it prints out correctly when I call it as is. However, my app can't retrieve the data in any kind of manner, it just returns as undefined.
In Home.js
var Method = require('../Services/Methods');
.
.
.
var ComponentTwo = React.createClass({
getInitialState: function() {
return {
text: 'Loading...',
}
},
componentDidMount: function() {
{
this.setState({
text: Method.loginUser(AccessToken)
})
}
},
render: function() {
console.log(Method.loginUser(AccessToken));
console.log(this.state.text);
I am in trial and error mode right now, but both of the logs returns undefined, except for my log in Methods.js, so I think there is an issue with just hitting return responseText, but I don't know any other way since they are in two separate files. So I think the issue is within Method.JS since calling it fails in every way I've tried.
I think you have to return a promise from your loginUser function, something like:
exports.loginUser = function(TOKEN) {
return new Promise((resolve, reject) => {
fetch(baseUrl + 'login' , {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
accessToken: TOKEN,
},)
})
.then((response) => response.text())
.then((responseText) => {
console.log(typeof responseText);
resolve(responseText);
})
.catch((error) => {
reject(error);
});
});
};
And then call your function like this:
Method.loginUser(AccessToken)
.then((res) => console.log(res))
.catch((error) => console.log(error))
.done();
I have not verified that the above code is working, it's just to give you an idea.