React Native refreshing data - reactjs

I'm trying to refresh some data when users re-vistis the screen. The way im using other places and it works. but can't figure out why this won't fly on this screen?
componentDidMount = () => {
this.props.navigation.addListener('didFocus', this.handleDidFocus)
}
async handleDidFocus() {
...
}
This is how I load data the first time and want to load it again when users revisits.
componentWillMount() {
this.getGroupAccepted();
}
async getGroupAccepted() {
if (this.state.token == null) {
var token = await AsyncStorage.getItem("token");
this.setState({ "token": token });
}
fetch('https://.../api/group/getActive', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
token: this.state.token
})
})
.then(response => response.json())
.then((data) => {
this.setState({
groups_accepted: data.groups_active,
loading: false,
});
})
.catch((error) => {
console.error(error);
});
}

This is what worked. Now when a user revisits the screen it loads the data once again.
componentDidMount = () => {
this.props.navigation.addListener('didFocus', this._handleDataChange)
}
_handleDataChange = () => {
this.getGroupAccepted();
}

Related

Can't send any header

I'm trying to access some data from my api using axios or fetch, but none of them is sending the headeri give them.
first the constructor of the react class
constructor(props) {
super(props);
this.state = {
loaded: false,
addresses: []
};
this.myHeaders = new Headers();
this.requestOptions = {};
this.token = `Bearer ${localStorage.getItem('token')}`
}
then the getAddresses function that should send a header with a token and get the addresses.
I'm showing you the 2 ways i used, but none of them worked.
first way
getAddresses() {
axios.default({
method: 'get',
url: "http://localhost:8090/address",
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
})
.then(response => {
this.setState({loaded:true, addresses:response.json()})
})
.catch(error => {
console.log('====================================');
console.log('error => ', error);
console.log('====================================');
})
}
second way
getAddressess () {
if (this.myHeaders.get("Authorization"))
this.myHeaders.set("Authorization", `Bearer ${localStorage.getItem('token')}`)
else
this.myHeaders.append("Authorization", `Bearer ${localStorage.getItem('token')}`)
if (this.myHeaders.get("Access-Control-Allow-Origin"))
this.myHeaders.set("Access-Control-Allow-Origin", `*`)
else
this.myHeaders.append("Access-Control-Allow-Origin", `*`)
if (this.myHeaders.get("Access-Control-Allow-Methods"))
this.myHeaders.set("Access-Control-Allow-Methods", 'GET')
else
this.myHeaders.append("Access-Control-Allow-Methods", `GET`)
this.requestOptions = {
method: 'GET',
headers: this.myHeaders
};
fetch("http://localhost:8090/address", this.requestOptions)
.then(response => {
this.setState({loaded:true, addresses:response.json()})
})
.catch(error => console.log('error', error))
console.log('====================================');
console.log(this.token);
console.log('====================================');
}

How to add user authentication with ReactJS Components

I want to implement a user authentication based on ReactJS component. I'm new to ReactJS and it's a group software project, so we don't use webhooks but components. The Authentication itself is working but not the rendering afterwards of the content.
In the app.js file I used conditional rendering, to either show the content or the login page:
if (this.getToken('token') === null || this.getToken('token') === undefined) {
shownComponent = <LoginComponent token={this.state.token} setToken={this.setToken} />;
} else {
shownComponent = <MainComponent />;
}
In the LoginComponent I implemented the following logic:
registerUser = () => {
const data = {
userName: this.state.userName,
userPassword: this.state.userPassword
}
return fetch('/users/createUser', {
method: 'post',
mode: 'cors',
headers:{
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json'
},
body: JSON.stringify(data),
})
.then((data) => {
if(data.status === 200){
console.log('User has been stored to database');
return true
}
})
.catch((error) => console.log( error.response.request) );
}
loginUser = () => {
return fetch('/login',{ headers:{
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json'
} })
.then((response) =>{
return response.json();
})
.then((data) =>{
return data;
});
}
login = async () => {
this.setState({loggedin: true})
const registered = await this.registerUser()
const userToken = await this.loginUser();
this.props.setToken(userToken)
}
after calling the login function from the login form (not copy pasted in here) it would only re-render the login page but not redirect back to the app.js and render now the main content.

Unhandled Rejection (TypeError): Cannot read property 'error' of undefined

I'm fairly new to React and I've been trying to create a SignUp page, however, I'm stuck in this error. Can someone give me any indication on what I should do in order to solve this error?
Signup Method:
// = Action =
// Sign up
export const signup = user => {
return fetch(
`${API}/signup`,
{
method: 'POST',
headers: {
Accept:'application/json',
'Content-Type' : 'application/json'
},
body: JSON.stringify(user)
})
.then(response => {
return response.json();
})
.catch(err => console.log(err));
}
Rewrite Signup method (ps: I only changed the .catch handler)
`
// Sign up
export const signup = user => {
return fetch(
`${API}/signup`,
{
method: 'POST',
headers: {
Accept:'application/json',
'Content-Type' : 'application/json'
},
body: JSON.stringify(user)
})
.then(response => {
return response.json();
})
.catch(err =>
console.log(err));
return err;
}
`
You need to wrap up your fetch logic inside a Promise to return a value to the caller.
export const signup = user => {
return new Promise((resolve, reject) => {
fetch(`${API}/signup`,
{
method: 'POST',
headers: {
Accept:'application/json',
'Content-Type' : 'application/json'
},
body: JSON.stringify(user)
})
.then(response => response.json())
.then(jsonData => resolve(jsonData))
.catch(err => resolve({error: `something went wrong err : ${err}`}));
})
}
signup(user).then(data => {
if (data.error) {
// handle error case
} else {
// handle success case
}
})
Now your signup method will return a value. Your data variable won't be undefined anymore.
I hope it helps, feel free to add comments or ask me more details

Unable to get response using fetch in React

I am trying to call 3rd party API, to fetch some data. I am getting the response in Postman, but not getting expected response when I execute my code.
I tried in 2 ways. Both ways I am getting "Promise pending".What could be the reason??
//request.js
Method 1
export const callSearchGiftsAPI = inputs => dispatch => {
dispatch(searchGifts());
let url = new URL(GIFT_SEARCH_API_URL),
params = {
apiKey: GIFT_SEARCH_API_KEY,
query: inputs.item,
country: 'us',
itemsPerPage: 3
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
return new Promise((resolve, reject) => {
setTimeout(() => resolve(
fetch(url, {
method: 'GET',
// mode: 'no-cors',
headers: {
'Content-Type': 'application/json',
Authorization: `secret ${SECRET}`
}
})
.then(res => {
if (!res.ok) {
return Promise.reject(res.statusText);
}
console.log("hi", res.json());
return res.json();
})
.then(gifts => dispatch(searchGiftsSuccess(gifts)))
.catch(err => dispatch(searchGiftsError(err)))), 500)
});
}
Method 2:
export const callSearchGiftsAPI = inputs => dispatch => {
dispatch(searchGifts());
let url = new URL(GIFT_SEARCH_API_URL),
params = {
apiKey: GIFT_SEARCH_API_KEY,
query: inputs.item,
country: 'us',
itemsPerPage: 3
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
fetch(url, {
method: 'GET',
// mode: 'no-cors',
headers: {
'Content-Type': 'application/json',
Authorization: `secret ${SECRET}`
}
})
.then(res => {
if (!res.ok) {
return Promise.reject(res.statusText);
}
console.log('result', res.json());
return res.json();
})
.then(gifts => dispatch(searchGiftsSuccess(gifts)))
.catch(err => dispatch(searchGiftsError(err)));
};
//form.js
class Form extend React.Component{
onSubmit(values) {
const inputs = Object.assign({}, values);
return this.props.dispatch(callSearchGiftsAPI(inputs));
}
//Remaining code
}
Also please note that I have installed CORS plugin in Chrome, to allow the request.If I disable it and add mode:'no-cors' I am getting as 401 unauthorized.What else am I supposed to do?
What happens is that you are creating a new Promise and returning it, but you are not waiting for it to resolve. You can either use then of the new async/await syntax to get the correct result :
onSubmit = async values => {
const inputs = Object.assign({}, values);
return await this.props.dispatch(callSearchGiftsAPI(inputs));
}
The code above will work with your first method.
Since your second method does not return anything, you will never get your result, you need to return your fetch's result and apply the code I gave above :
return fetch(url, {
This worked.
I was trying to put console.log in the wrong place and hence was not able to see the response properly.
export const callSearchGiftsAPI = inputs => dispatch => {
dispatch(searchGifts());
let url = new URL(GIFT_SEARCH_API_URL),
params = {
apiKey: GIFT_SEARCH_API_KEY,
query: inputs.item,
country: 'us',
itemsPerPage: 3
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
console.log(url);
return fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `secret ${SECRET}`
}
})
.then(res => {
console.log('result');
return res.json();
})
.then(response => {
console.log(response); // changed
dispatch(searchGiftsSuccess(response.items));
})
.catch(err => dispatch(searchGiftsError(err)));

setState not working with forloop in react function

I am nesting two api calls inside componentDidMount, everything working fine, the only issue I have is the state do not update so I put some console logs to see what's going on
fetch reviews done!
analysis done!
false
analysis done!
false
analysis done!
false
As you can see the state of loaded never get updated and by the way no data show up on the application, I probably messed up the logic with this function but I can't figure this out.
componentDidMount = () => {
this.setState({ loading: true });
fetch(
"https://url-one.com",
{
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"X-Spree-Token": "xxx"
}
}
)
.then(response => response.json())
.then(responseJson => {
console.log('fetch reviews done!')
this.setState(
{
list: responseJson.reviews,
},
() => {
var obj = this.state.list;
var data = [];
for (let i in obj) {
fetch(
"https://url-two.com",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
api_key: "uuu",
data: obj[i].text
})
}
)
.then(response => response.json())
.then(responseJson => {
data.push({'review': obj[i].text, 'analysis': responseJson.results * 100});
});
this.setState({
data: data,
loaded: true,
loading: false,
});
console.log('analysis done!')
console.log(this.state.loaded)
}
}
);
});
}
Of course if I use a separate function to update the state it works!
show = () => {
this.setState({ loaded: true });
};
As you can see the state of loaded never get updated
Because the setState happens asynchronous (not immediately update), using console.log(this.state.loaded) like that won't work as expected, instead, you might use the setState callback as you did with the second fetch, like so:
this.setState(
{
data: data,
loaded: true,
loading: false
},
() => {
console.log('analysis done!');
console.log(this.state.loaded);
}
);
EDIT
I think we should use Promise.all() to make it work, like this:
componentDidMount() {
this.setState({ loading: true });
fetch('https://url-one.com', {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'X-Spree-Token': 'xxx'
}
})
.then(response => response.json())
.then(responseJson => {
console.log('fetch reviews done!');
this.setState(
{
list: responseJson.reviews
},
() => {
var obj = this.state.list;
var data = [];
var fetchArr = [];
for (let i in obj) {
let promise = fetch('https://url-two.com', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
api_key: 'uuu',
data: obj[i].text
})
}).then(response => response.json());
fetchArr.push(promise); // make an array of promises
}
Promise.all(fetchArr).then(values => { //after all promises resolved, we'll receive an array of responseJson, we'll loop through it
values.forEach((responseJson, i) => { //for each responseJson, we push it to the data array
data.push({
review: obj[i].text,
analysis: responseJson.results * 100
});
});
// finally, we update state
this.setState(
{
data: data,
loaded: true,
loading: false
},
() => {
console.log('analysis done!');
console.log(this.state.loaded);
}
);
});
}
);
});
}
You have a couple conflicting processes here that need to get shored up. You don't want to modify state during async actions because internally you will fire off a re-render, so I'd suggest reorganizing a bit. The loaded state is not resolving correctly because you aren't waiting for your subsequent requests to finish. Here is an example:

Resources