My effect is:
#Effect({dispatch: false}) /* sends request to httpService with params as login credentials on instance of loginAction. */
login$: Observable<Action> = this.actions$
.instanceOf(LoginActions.LoginAction)
.switchMap(
action => {
return this.loginHttpService.login(action.payload)
.map( (res: any) => {
if (res && res.message !== 'Invalid Login') {
const firstName = res.firstName;
const lastName = res.lastName;
this.tokenService.setToken(res.jwt);
this.tokenService.setFirstName(firstName.charAt(0).toUpperCase() + firstName.slice(1));
this.tokenService.setLastName(lastName.charAt(0).toUpperCase() + lastName .slice(1));
this.tokenService.setId(res.id);
this.tokenService.setAvatar(firstName.charAt(0).toUpperCase() + lastName.charAt(0).toUpperCase());
const permissions = res.roles
this.tokenService.setUserRoles(permissions)
return Observable.create(observer => {
console.log('in observable')
this.permissionsService.loadPermissions(permissions, () => {
observer.next({
type: 'string'
});
console.log('here we go')
this.store.dispatch(new LoginActions.LoginSuccessAction({user: res}))
return observer.complete();
})
})
}
})
.catch( (e:any) => {
this.store.dispatch(new LoginActions.LoginFailureAction(true));
return Observable.create(observer => {
return observer.complete();
})
});
});
The in observable log never fires. What am I doing incorrectly?
Sorry but I don't understand why you need to create a new Observable.
In this kind of situation, here is what I'm used to do :
#Effect()
login$ = this.actions$
.ofType<LoginAction.LoginAction>(LoginActions.LOGIN_ACTION)
.pipe(
map(action => action.payload),
switchMap(payload => {
return this.loginHttpService.login(payload)
.map(userLogged => {
return new LoginActions.LoginSuccessAction({user: userLogged});
})
.catch(error => {
return new LoginActions.LoginFailureAction(true);
});
})
);
#Effect()
loginSuccess$ = this.actions$
.ofType<LoginAction.LoginSuccess>(LoginActions.LOGIN_SUCCESS)
.pipe(
map(action => action.payload),
switchMap(payload => {
return this.permissionsService.loadPermissions(payload.user)
.map(permissions => {
return new LoginActions.PermissionsLoaded(permissions);
})
.catch(error => {
return new LoginActions.PermissionsLoadingFailed();
})
})
);
If existing loadPermissions method doesn't return an Observable, a new method as below can do the job :
loadPermissions(user): Observable<Permissions> {
return Observable.create(observer => {
loadPermissionsWithCallback(user, (response) => {
observer.next(response);
return observer.complete();
});
});
}
It's a chain of actions. LOGIN_ACTION -> LOGIN_SUCCESS -> PERMISSIONS_LOADED.
User is fully logged when action PERMISSIONS_LOADED is dispatched.
Each service method (login and loadPermissions) should return an Observable, and it's the case with new HttpClientModule.
Of course, it's just a simplified and incomplete example... Hope this will help you a little bit.
Related
useEffect(() => {
initEngine();
return () => {
engine?.destroy();
};
}, []);
const initEngine = async () => {
if (engine) return;
engine = await RtcEngine.createWithContext(new RtcEngineContext(appId));
addListeners();
await engine?.enableVideo();
await engine?.startPreview();
await engine?.setChannelProfile(ChannelProfile.LiveBroadcasting);
await engine?.setClientRole(ClientRole.Broadcaster);
}
const addListeners = () => {
engine?.addListener('Warning', warningCode => {
console.info('Warning', warningCode);
});
engine?.addListener('Error', errorCode => {
console.info('Error', errorCode);
});
engine?.addListener('JoinChannelSuccess', (channel, uid, elapsed) => {
console.info('JoinChannelSuccess', channel, uid, elapsed);
setIsJoined(true);
});
engine?.addListener('LeaveChannel', stats => {
console.info('LeaveChannel', stats);
setIsJoined(false);
setRemoteUid([]);
});
engine?.addListener('UserJoined', (uid, elapsed) => {
console.info('UserJoined', uid, elapsed);
setRemoteUid([...remoteUid, uid]);
});
engine?.addListener('UserOffline', (uid, reason) => {
console.info('UserOffline', uid, reason);
setRemoteUid(remoteUid.filter(value => value !== uid));
});
};
This is my code example.
I take Warning 8 and Warning 16.
My camera doesn't come out.
But the other person can see my face.
I don't know how to solve the error code even if I look at it.
The error returned is : undefined is not an object (evaluating 'json.map') ,knowing that my api has multiple data.
The code i use to fetch data is :
CheckifReadLater = async () => {
const username = await AsyncStorage.getItem('username');
const isLoggedIn = await AsyncStorage.getItem('isLoggedIn');
if (isLoggedIn == 1 && username) {
await fetch(Config.backendAPI+`/readlater.php?username=${username}&select`)
.then((response) => {
reactotron.log("Response : ",response);
response.json();
})
.then((json) => {
json.map((product, index) => {
if (product.id == this.props.product.id) {
this.setState({
isReadLater: true,
})
}
});
})
.catch((error) => reactotron.log('This is the error: ',error))
}
reactotron.log("Readlater : ",this.state.isReadLater);
}
How can i solve this problem ?
You should return the response.json(); on the first .then function for it to be available on the next .then.
Do this:
await fetch(Config.backendAPI+`/readlater.php?username=${username}&select`)
.then((response) => {
reactotron.log("Response : ",response);
// update your code here
return response.json();
})
I have made a function that checks for internet availability. whenever I call this function it gives me true every time whether the internet is ON or OFF. I want to have one function that contains code to check the internet and I can call it before fetching data from the internet . my code is below.
const [campusList, setCampusList]= React.useState([{label:'Select Campus', value:'select campus'}]);
const isConnected =()=>{
NetInfo.fetch().then(state => {
console.log("Connection type", state.type);
console.log("Is connected?", state.isConnected);
if(state.isConnected)
return true;
else
return false;
});
}
const loadCampuses = async()=>{
if(isConnected)
{
await fetch(url)
.then((respons)=>respons.json())
.then((jsonResponse)=>{
jsonResponse.map((data)=>
setCampusList(campusList=> [...campusList, {label:data.Text, value:data.Value}])
);
})
.catch((error)=>console.log(error))
//.finally(()=>setLoading(false))
}
}
fetch Returns a Promise that resolves to a NetInfoState object. you need to wait promise to resolve
try this
const isConnected = sendRequest => {
NetInfo.fetch().then(state => {
if (state.isConnected) {
sendRequest();
}
});
};
const loadCampuses = () => {
isConnected(async () => {
await fetch(url)
.then(respons => respons.json())
.then(jsonResponse => {
jsonResponse.map(data =>
setCampusList(campusList => [
...campusList,
{ label: data.Text, value: data.Value },
]),
);
})
.catch(error => console.log(error));
});
};
oh right, it's a promise, not just a straight return. you need to await for it. You don't need a separate function:
if(await NetInfo.fetch().isConnected)
I have a store for notifications in my application. I can load all notifications and mark one notification as read. I wrote actions and mutations for each case. The last action is for marking all notifications as read but I am struggling with writing a mutation for this (commented part).
const actions = {
notifications(context) {
document.client
.get_notifications()
.then(ca => {
S_Helper.cmt_data(ca, "load_notifications", this);
})
.catch(error => {
ClientAlert.std_fail_with_err(error);
});
},
readNotification(id, params) {
document.client
.read_notification({ id, params })
.then(ca => {
if (ca.is_success()) {
context.commit("mark_notification", id);
} else {
ClientAlert.std_fail();
}
})
.catch(error => {
ClientAlert.std_fail_with_err(error);
});
},
readAllNotifications(context, params) {
params = params || {};
document.client
.read_all_notifications(params)
.then(ca => {
if (ca.is_success()) {
context.commit("mark_all_notifications", this);
} else {
ClientAlert.std_fail();
}
})
.catch(error => {
ClientAlert.std_fail_with_err(error);
});
}
};
const mutations = {
load_notifications(context, data) {
context.notifications = data;
},
mark_notification(state, id) {
let new_data = state.notifications.map(function(element) {
if (!!element.id && element.id === id) {
element.viewed = true;
}
return element;
});
state.notifications = new_data;
}
//mark_all_notifications(context, data) {
//}
};
mark_all_notifications(state, data) {
state.notifications = state.notifications.map(notification => {
notification.viewed = true
return notification
})
}
A simple map should work.
Does anyone have an example on how to use promise with GraphRequestManager?
I get Cannot read property then of undefined error in my action creator.
function graphRequest(path, params, token=undefined, version=undefined, method='GET') {
return new Promise((resolve, reject) => {
new GraphRequestManager().addRequest(new GraphRequest(
path,
{
httpMethod: method,
version: version,
accessToken: token
},
(error, result) => {
if (error) {
console.log('Error fetching data: ' + error);
reject('error making request. ' + error);
} else {
console.log('Success fetching data: ');
console.log(result);
resolve(result);
}
},
)).start();
});
}
I call the above using my action creator
export function accounts() {
return dispatch => {
console.log("fetching accounts!!!!!!");
dispatch(accountsFetch());
fbAPI.accounts().then((accounts) => {
dispatch(accountsFetchSuccess(accounts));
}).catch((error) => {
dispatch(accountsFetchFailure(error));
})
}
}
I get 'Success fetching data:' in the console along with the result before the error. So the API call is made successfully. The error is after fetching the accounts in fbAPI.accounts().then((accounts) which I think is due to GraphRequestManager returning immediately instead of waiting.
I have a solution for you.
My provider look like this :
FBGraphRequest = async (fields) => {
const accessData = await AccessToken.getCurrentAccessToken();
// Create a graph request asking for user information
return new Promise((resolve, reject) => {
const infoRequest = new GraphRequest('/me', {
accessToken: accessData.accessToken,
parameters: {
fields: {
string: fields
}
}
},
(error, result) => {
if (error) {
console.log('Error fetching data: ' + error.toString());
reject(error);
} else {
resolve(result);
}
});
new GraphRequestManager().addRequest(infoRequest).start();
});
};
triggerGraphRequest = async () => {
let result = await this.FBGraphRequest('id, email');
return result;
}
That works great ! I let you adapt my solution to your system.