I can't figure this out, if you can point me to right direction. On my NavMenu.js I have LogIn (two inputs and a submit button, on which I call handleSubmit()
In handleSubmit()
I am checking for user login credentials which works great, but after I confirm login, i procede with doing next fetch for checking user roles (and returning promise) and visibility in application
Helper.js
function getAllRoles(formName, sessionVarName) {
var roleData = [];
var roleId = sessionStorage.getItem('UserLoggedRoleId');
fetch('api/User/GetUserRole/', {
'method': 'POST',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
'body':
JSON.stringify({
'roleId': roleId,
'formName': formName
})
}).then(roleResponse => roleResponse.json())
.then(data => {
sessionStorage.setItem(sessionVarName, JSON.stringify(data));
roleData = data;
});
var result = Promise.resolve(roleData)
return result;
}
function checkRoleVisibility(userRoles, role) {} <-- return true or false
export {
getAllRoles ,
checkRoleVisibility
};
In NavMenu.js
import { getAllRoles, checkRoleVisibility } from './common/Helper';
handleSubmit() {
fetch('api/User/UserAuthentification/',
....then(response => {
if (response.ok) {
this.setState(prevState => ({ userLogged: !prevState.userLogged }))
response.json().then(value => {
sessionStorage.setItem('UserLogged', true);
sessionStorage.setItem('UserLabelSession', this.state.userLabel);
sessionStorage.setItem('UserLoggedRoleId', value.userRole.roleID);
getAllRoles('NavMenu', 'UserLoggedRoles')
.then(roleData => {
this.setState({
loggedUserRoles: roleData,
loading: false
});
});
this.props.alert.success("Dobro dosli");
})
}
}
But here comes the problem, is that in render()
itself, I have a control navBar
which calls
checkRoleVisibility(this.state.loggedUserRoles, 'SeeTabRadniNalozi')
from helper, which send this.state.loggedUserRoles
as parameter, which suppose to be filled in fetch from handleSubmit()
but it's undefined, fetch finish, set loading
on true, rendering completes and it doesn't show anything
I have this.state.loading
and based on it I show control ...
let navMenu = this.state.loading ? <div className="loaderPosition">
<Loader type="Watch" color="#1082F3" height="200" width="200" />
</div> : !this.state.userLogged ? logInControl : navBar;
If I put a breakpoint on controler I can see my method is being called by getAllRoles
function, but also I can see that application keep rendering on going and doesn't wait for promise to return to fill state of loggedUserRoles
.
So question is, why rendering doesn't wait for my role fetch nor doesn't wait for promise to resolve before setting loading on true?
I checked this answer Wait for react-promise to resolve before render and I put this.setState({ loading: false });
on componentDidMount()
but then loading div is shown full time
From what I see and understand is, that you're calling
this.setState(prevState => ({ userLogged: !prevState.userLogged }))
if the response is okay. This will lead in an asynchronous call from React to set the new State whenever it has time for it.
But you need the resource from
this.setState({
loggedUserRoles: roleData,
loading: false
});
whenever you want to set userLogged
to true, right?
So it might be that React calls render before you set the loggedUserRoles
but after userLogged
is set to true. That would result in an error if I understand you correctly.
You could simply set the userLogged
state with the others together like this:
this.setState({
userLogged: true,
loggedUserRoles: roleData,
loading: false
});
EDIT:
Moreover you want to change your Promise creation inside of getAllRoles. You're returning
var result = Promise.resolve(roleData)
return result;
This will directly lead to the empty array since this is the initial value of roleData
. Therefore you're always returning an empty array from that method and don't bother about the fetched result.
You've multiple ways to solve this. I would prefer the clean and readable way of using async/await:
async getAllRoles(formName, sessionVarName){
var roleId = sessionStorage.getItem('UserLoggedRoleId');
const response = await fetch(...);
const data = response.json();
sessionStorage.setItem(sessionVarName, JSON.stringify(data));
return data;
Or if you want to stay with Promise:
function getAllRoles(formName, sessionVarName){
return new Promise((resolve, reject) => {
var roleId = sessionStorage.getItem('UserLoggedRoleId');
fetch(...)
.then(roleResponse => roleResponse.json())
.then(data => {
sessionStorage.setItem(sessionVarName, JSON.stringify(data));
resolve(data);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With