I'm implementing a meeting app that uses Amazon's Chime SKD React. Here is the
link of the library. I successfully implemented a meeting, and it works well. However, there is a small issue which with which I'm not satisfied.
There are several meeting statuses that Chime provides.
Here is the enum of the meeting status:
enum MeetingStatus {
Loading,
Succeeded,
Failed,
Ended,
JoinedFromAnotherDevice,
Left,
TerminalFailure
}
These statuses are managed by the useMeetingStatus hook from the SDK itself. I think the statuses are pretty much self explanatory.
You enter a meeting, you get the MeetingStatus.Succeeded status. You leave the meeting you get the MeetingStatus.Left status.
And here is the problem:
Once you leave a meeting and try to enter a new one, you get for a moment MeetingStatus.Left status, and then you get the initial meeting status which should be MeetingStatus.Loading.
So my question is, is there a way to reset the meeting status after the user leaves a meeting with the meetingManager.leave() method?
I also noticed after leaving a meeting and hard reloading the app (page), this doesn't happen, which for me means, there is some state that should be reset after leaving a meeting.
There is a <MeetingProvider> component which wraps the the meeting app. This meeting provider holds all data in the useMeetingManager hook. The solution was to re render the <MeetingProvider> which I did by wrapping the router component with it.
Once the user leaves the meeting, the app redirects the user to other page and the <MeetingProvider> re renders.
Or, there is also a solution to instantiate a new meetingManager object like this:
const meetingManager = new MeetingManager(new ConsoleLogger('LoggerName'));
and then you pass the meetingManager to the <MeetingProvider> like this:
<MeetingProvider meetingManager={meetingManager}>
<MyApp1 />
</MeetingProvider>
This is described here
Related
I have a typescript DataStore object that stores some data (using Mobx) from the server when I login. For example:
import { observable } from 'mobx-react';
class DataStore {
#observable user: User | null = null;
lots more code here
}
The DataStore class has a doLogin method, and when that is successful it populates the user object with data of type User (which is an interface I defined elsewhere - it contains a number of user data fields like username, email etc).
Now, when or if the user refreshes the page or tab, the stored User data goes away. This of course will cause problems if I try to use it.
So what is the best pattern to use here? One thing to do is to save this data in localStorage or sessionStorage or localForage, but I have heard some horror stories about this not working in some edge situations. Another possibility is to check to make sure it exists and if not then use the dataStore object.doLogin method to reload it.
What do most developers do in this situation?
I don't think this is a mobx problem, rather a general strategy on how to fetch data.
If you choose to back up the data locally, then make sure you version the data, so when your code or data model changes, you can skip the local data and fetch again. This way you won't have any problems with locally saved data.
I am building a React app (with react-redux, redux-saga, and axios), and
I need advice on how to arrange my project for displaying user-friendly error messages.
(It is up to me to decide what and how I display to the user)
In particular, I would like to get answers to the following questions:
Should I display a message based on the status code?
Should I break down the errors to client / server / other errors and what are the benefits of that? (based on example from Axios)
Where should I keep the error messages, in the component itself, in a config file (I would like to see an example of such a file)?
How would my redux state tree look?
Should I dispatch an action for every error based on the status code?
I would appreciate any suggestions or real-world examples.
Here are some examples of error responses from our backend:
Request URL: https://example.com/api/call/123
Request Method: POST
Status Code: 400 Bad Request
Request URL: https://example.com/api/call/123
Request Method: PUT
Status Code: 409 Conflict
Request URL: https://example.com/api/user/me/
Request Method: GET
Status Code: 401 Unauthorized
It basically depends on what method you are trying to display the message, For instance, in our own projects, We are using a global snack bar component to display errors if any have occurred during the requests.
Most of the time users don't care about the status code, if you want not to be very specific then you can display a simple alert/snack bar for example: "Sorry, Some error occurred".
If you are sure that you do need to show specific errors to the user the I definitely recommend a constant file for errors which will store all your error message, You can keep them in constants directory in the store folder so maybe even in /helpers, It depends on your choice.
Yep, you can definitely divide your errors based on if the error was on the server or the client-side.
I don't think the redux tree will change if you're not managing errors in the tree. If you want to, definitely use a snack bar/alert reducer on the top of the tree
You may not want to show the same error for a status code in each of different components, Otherwise, if you want to, You can use it but that would add a lot of unnecessary code into your requests.
For our projects, since we are using i18 for internationalization, We have a snack bar reducer and the action folder, We import the snack bar actions in our sagas and just display a simple error message ( You definitely can customize it for your needs accordingly), That's all,Keep it simple.
yield put(Actions.apiRequest);
try {
const res = yield axios.put('/todo/', updateData);
if (res.data.status === 'success') {
yield put(Actions.fetchTodos(todoID));
yield put(snackbarSuccess('Todo Saved Successfully !'));
} else {
throw new Error();
}
} catch (error) {
yield put(Actions.apiError);
yield put(snackbarError(REQUEST_FAIL)); // an imported constant
}
Some basic code behind my implementation.
1) Assuming you're also doing the BE or can ask someone to adjust the response - It might be best to return a body with your API error response, and avoid just HTTP status codes - if possible. That could then contain an error 'code' that maps to a message on your front-end, as well as field name which can be really helpful for displaying errors in the right place on forms, etc. alternatively, the entire message could come from the BE and the FE simply display it. I work on an enterprise-level codebase that uses both these methods.
2) Regarding error message, i'd always store them in a common file but beyond that up to you really. It sort of depends on how you implement #1. Personally I like error 'codes' stored in an enum file, which correspond to a message because you can then do other logic from that (e.g. don't display the rest of a form if error X is triggered, use a custom message for the error code in one situation or fall back to a default
3) Not sure - I guess you'd do that if you want to log server-side errors but show client. Where I work we differentiate purely for different logging categories I think.
4) Again depends on your implementation - somewhat up to you. Some form packages will handle this for you in redux. Others will just use local state and not redux for this.
5) Would make sense to, yes. Again if you look a custom error code returned in the body of the API call that'll give you more flexibility.
I hope that gives you some ideas, based on my experience rather than any set way of thinking.
have a look at https://reactjs.org/docs/error-boundaries.html as well, and if you haven't already REST APIS / best practice for REST API: https://blog.restcase.com/rest-api-error-codes-101/
I know that "best practices" type of questions are frowned upon in the StackOverflow community, but I am not sure how else to word this.
My "big picture" question is this:
What is a good practice when it comes to handling "session" state in a stateless server (like one that provides a REST api)?
Quick details
Using nodeJS on backend, MongoDB for database.
Example 1: Login state
In version 1 of the admin panel, I had a simple login that asks for an email and password. If the credentials are correct, user is returned a token, otherwise an error.
In version 2, I added a two-factor authentication for users who activate it.
Deciding to keep things simple, I have now two endpoints. The flow is this:
/admin/verifyPassword:
Receive email and password;
if(Credentials are correct) {
if(Admin requires 2fa) {
return {nextStep: 2fa};
} else {
return tokenCode;
}
} else {
return error;
}
/admin/verifyTotpToken:
Receive email and TOTP token;
Get admin with corresponding email
if(Admin has verified password) {
return tokenCode
} else {
return error;
}
At the verifyTotpToken step, it needs to know if the admin has already verified password. To do that I decided to attach a 'temporary' field to the Admin document called hasVerifiedPassword which gets set to true in verifyPassword step.
Not only that, but I also set a passwordVerificationExpirationDate temporary field in the verifyPassword endpoint so that they have a short window within which they must complete the whole login process.
The problem with my approach is that:
It bloats the admin document with ephemeral, temporary state that has nothing to do with an admin itself. In my mind, resource and session are two separate things.
It gives way for stale data to stay alive and attached to the admin document, which at best is a slight nuisance when looking through the admin collection in a database explorer, and at worst can lead to hard to detect bugs because the garbage data is not properly cleaned.
Example 2: 2FA activation confirmation by email
When an admin decides to activate 2fa, for security purposes, I first send them an email to confirm that it is truly them (and not someone who hijacked their session) who wanted to activate 2fa. To do that I need to pass in a hash of someway and store it in the database.
My current approach is this:
1) I generate a hash on the server side, store it in their admin document as well as an expiration date.
2) I generate a url containing the hash as a query parameter and send it in the email.
3) The admin clicks on the email
4) The frontend code picks up the hash from the query parameter and asks the server to verify it
5) The server looks up the admin document and checks for a hash match. If it does, great. Return ok and clean up the data. If not, return an error. If expired, clean up the data.
Here also, I had to use some temporary state (the two fields hash and expirationDate). It is also fragile for the same problems mentioned above.
My main point
Through these two examples I tried to illustrate the problem I am facing. Although these solutions are working "fine", I am curious about what better programmers think of my approaches and if there is a better, more idiomatic way of doing this.
Please keep in mind that the purpose of my question is not a get a specific solution to my specific problem. I am looking for advice for the more general problem of storing session data in a clever, maintainable, way that does not mix resource state and ephemeral state.
For a simple RESTful type of app, say, if it is blog posts, then when we see the list of all posts, and navigate to see just one post, should we actually set the app state's posts to [] or null?
And when we navigator from one post back to seeing all posts, should we set the app state's post to null as well?
(We do that probably in the componentWillUnmount() function:
componentWillUnmount() {
this.props.clearPost();
}
where the clearPost() is an action creator for action type CLEAR_POST, and the reducer will return null when it sees this action type.)
Why? Because when the user sees a list of all posts, and now click on one post, we will see one post. But what if the network is down or slow? Then we will see the previously loaded post which could be a different post or even a deleted post. If the network is down, we see this wrong record and it will stay there. If the network is slow or unstable, we see this wrong record and after N seconds, we will see the correct record.
The same with the full list of posts. When we navigate from other components (such as the show one post component) back to this index page, if the network is down or slow, we will also see the wrong content of the list of posts. And then if network is down, this wrong list will stay. If network is slow, then the wrong list will be corrected after N seconds.
And what if customer service representatives are using this app? They might say to the customer, "NO, I see this record (or list), and it says such-and-such. According to the record, you are [...]. Computers do not lie, sir".
So is it always recommended to set the app state for that component back to empty array or null always, in the componentWillUnmount() function? Essentially, if we do have a constant called INITIAL_STATE for this component, we set it back to INITIAL_STATE?
I'm trying to figure out a user friendly way to pass messages to users from my Apex code. I have a trigger which fires after insert/update of a lead, which then filters the list of updates and triggers a #future method which pushes the lead data out to an external web service and updates the converted account with some of the returned values.
I'd like to do the following (where X, Y and Z are any number of leads from 1 to 50)
notify the user converting the leads that leads X, Y and Z will be exported (I'll know this during the trigger execution).
notify the user whether the export succeeded or failed (which will be known for each of X, Y and Z when the #future method runs).
What is the recommended way to pass this information back to the user? I'd prefer not to use email (as this would trigger one email per record, which is pretty spammy and unpleasant). Is there another way to inject notification messages into a page? I've tried ApexPages.addMessage() but it doesn't seem to do anything for me (no error, but no notice either).
addMessage() works with both Visualforce pages and standard pages when there's a current page active, so using this in the trigger should work fine if the user is firing the action from a button / VF page. Using this won't work from your #future method however because it runs asynchronously in the background.
Maybe the best solution would be to use a custom message object, which has a list of fields modified, when, and has a lookup to the appropriate user (or uses them as the owner). You could then create a simple VF page and controller which when viewed queries for records in that object related to the current user and provides an option to delete them (you could automatically delete them after pulling them from the DB but you run the risk of the user not actually noticing a message). You can then take this page and use it as part of a dashboard component, so anytime the user is viewing their Home page they could see a list of notifications.
Finally another option might be making use of Chatter, pumping the messages to the user via that which will then also show up in digest emails etc..