Dynamic welcome <user> of navbar in reactJs - javascript

I have a doubt regarding dynamically rendering the logged in user's name in the NavBar in react.
So my app is structured in the following way
<App>
<Header/>
<Router>
....
<Router/>
<Footer/>
<App/>
Now inside the header component, I need to display "Welcome <user>" whenever the user is logged in. Here are some solutions that I thought of,but Not sure if I'm missing out on anything.
To send it as a prop to the header. But it can only be dynamic if I do a setState in the App component and re render the entire app component (Which I want to avoid)
To store it in redux, so header can dynamically get the updated. But since I am using JWT, and the user needs to stay logged in, If the user refreshes the page, store content will be wiped out.
I can store the username in localstorage as well, but the entire app would still need to be re rendered in order to display the change
-) I think it can be accomplished in Angular by BehaviorSubject, but in this scenario, I'm clueless.
Is there any solution or method that I am missing?
Thanks in advance

At first if you want to keep your user logged in then you have to store the JWT somewhere. Here by 'somewhere' I mean, so that you can access it on next reload.
In my maximum project I store my JWT in local-storage. It works something like this
When user logs in I store the JWT in local-storage also in my reducer.
Then on my 'Inital State' I always take the local-storage so that if we have anything in the local-storage it means user is logged in
initial_state = {
userName: localstorage.getItem('user_name')
}
That's how you can keep your user logged in and at the time of logout erase the local-storage as well as the reducer.

You can send the user as a prop to the header. That is kind of the preferred method. Have the user login and save their app state with redux of the useState hook that is now available in React.
To your second question, JWTs preserve session data. Rerendering the page won't cause that to disappear. Well-designed apps have JWT with an expiration time (usually 20 minutes or less).
I worked on a voting application that did exactly what you're looking for and did not require any global state management. Feel free to pick through it. It's an open-source project. I think we used Auth0 or Google's Oauth library to do authentication.
Here's the code for the React header(navbar): https://github.com/poll-pal/poll-pal/blob/master/src/Components/Header/Header.js
Here's the code for the Express server that backed it: https://github.com/poll-pal/poll-pal/blob/master/server/routes/auth.js

Related

Creating A 'User Only' Section In A Firebase Site

I'm hoping to be able to create a section of a site that is unable to be read/seen by anyone that's not logged in... I am using Firebase and Javascript
I have read that you are unable to set permissions for files (.htmls ect) so i wont be able to block people from seeing the pages as a whole... Ive also read that this isn't the best practice anyway... So my question is...
What is the protocol for doing this sort of thing? And how can this be done in Firebase?
I have managed to create a user only page before from a tutorial, but this was just done by hiding the content of the page with Javascript and also blocking the permissions to the displayed data through Firestore permissions.
But I don't feel this is adequate for my site as I don't want people being able to read the code in the background or get access to the page at all to begin with.
I have also read that a way to go about doing this is to use Firebase Cloud Functions to check weather the user is logged in and if they are then it spits out the code for the pages from the google servers. Is this a good idea? Or is there a better way?
Any help, tips or insights would be greatly appreciated.
Just trying to get a feel for where to begin with this problem.
Hoping there is a solution.
Thanks
Yes, its a good practice hiding or preventing the UI to be rendered for unauthorize users.
Yes, its also a good practice setting the permissions accessing your data from the database.
You should also consider middleware, navigation guards or route guards for preventing unauthorized users to visit the restricted page. It would depend on the stack, or what frontend technology you are using. You can find whatever navigation guard you chosse. For vuejs there is vue-router. Also you can use firebase authState listener. Depends on your choice.
Use firebase auth to signInWithEmailAndPassword, or whatever your authentication method was. Then, you can check the auth state in onAuthStateChange, and set your new userId state:
// somewhere...
const [currentUserId, setCurrentUserId] = useState(null)
// later..
onAuthStateChanged(auth, (user) => {
if (user && user.uid) {
setUserId(user.uid)
}
});
// even later in this component:
return (<Layout userId={currentUserId} />);
// in wherever you have links, I assumed you passed currentUserId to here:
return (
currentUserId != null ? (Give content pls) : routeToLogin();
);
Something like this should be fine and secure enough. Noone is gonna go and flip a variable in your extremely obfuscated, transpiled javascript code generated by your bundler, and even if they did find a place to flip a variable, the code would probably throw an error anyway.
You could lazy load that certain page as well once authenticated, then the code for it it wouldn't even be loaded into the users disk until they've successfully signed in.

How to reload the component when the state of another component changes React

I am making an e-commerce app with react and firebase the <cart /> component contains two child components
1-<BasketItem /> (this component will be duplicated as many Items as the user adds to the cart and it has the functionality to let user modify the quantity of the Item )
2- <OrderSummary /> (this component will show the user the the total price of his cart and the shipping fees)
of course all the data of the items and the total will be gotten from the database (I am using firestore) but but the issue is when the user update the quantity of the items from the <BasketItem /> component the total price from the <OrderSummary /> did not get updated as well because the database call will be done already and no way to recall the function that gets the data from the database because there is no parent- child relation between the two components and I can't pass props between them I have tried to use react-context-api for this but that did not solve the issue because the up to date is on the database and the only way to update the total value is to refresh the page and this is not a good user experience to have.
In any React all, all affected UI components should be updated when you update the cart information in the state (as they should all be observing that).
When using Firestore, you'll use a so-called CQRS pattern, where the updates sent to the database, are a separate stream from the listeners to the database. You'll typically add listeners when you create/mount the components, so that they're always listening while the component is visible to the user.
With that setup in place, the update flow becomes:
Your code write a new value to the database through the Firebase SDK.
This gets written to the database on the server at some point.
The servers sends this information to all other clients, and a confirmation to the client who wrote the value.
This triggers the listener that you registered before.
The listener updates the data in the state of the app.
And that then finally triggers a repaint of the affected components.
This is the general flow, but it applies to all cases I can think of.
Usually the best practice is to have the state stored on the front-end too in the form of context-api or redux-store or simply as component's state, they try syncing this state on the front-end with DB when user triggered submit/order action.
If you had to update your DB on every quantity change, then you have to update the same on front-end state/redux-store too.

How can we use the same state across multiple tabs (pages)?

I have a page in my application that is an interactive chart with a bunch of settings (filters, time ranges, etc). I'd like to store them in-app state because some of the settings may be used by other components on another page, but right now if I click on any other tab and come back to the previous tab then the page shows the initial state(chart is gone, filtered data gone, date range showing the default value, dropdowns shows default ass well). And the state is also showing null.
Anything in your component state is dynamic; i.e., it is temporary. If you refresh the window, the old state is lost. A similar thing happens when you open a fresh tab—you get the state declared in your constructor. You can use any of the following if you want the state data in another tab:
Simply using redux won't solve your problem as redux store is also related to a specific browser tab. If you would like to persist your redux state across a browser refresh, it's best to do this using redux middleware. Check out the redux-persist, redux-storage middleware.
If you are using react-router you can simply pass required state through the link when you open a fresh tab. Here's an example:
<Link to={{
pathname: '/pathname',
state: { message: 'hello, im a passed message!' }
}}/>
Simply store the data in localStorage and access localStorage in other tabs.
If you are looking to use a variable across the entire application you can also use localStorage
localStorage.setItem('move', this.state.move);
also don't forget to unset it when you are done!
localStorage.removeItem('move');
The straight forward solution to this is redux-state-sync. It will just work and the store will be updated on all tabs and even windows on the browser.
I think you should implement react-redux into your app.
React-redux is a state management tool that manage the state of your application at a centralized location and you access data from store at anytime from anywhere.
React-redux:
https://redux.js.org/basics/usage-with-react
You some library for state management. The most popular one that's used with React is redux.
https://redux.js.org/introduction

Angular routing after authentication

Actually I am struggling for correct routing after successful login authentication in complex web app on Angular js 2. I am following following link:
https://github.com/auth0-blog/angular2-authentication-sample
I make understand code but the issue is after successful login if I again change url to /login in again takes me to login screen where I have login form, but my concern is why I have been redirected to login screen although I know current code do so but how can I resolve this and achieve navigation in correct way.
Please help that what is the correct way to achieve the same.
Inside login add a condition to check if id_token is present in localstorage and it is not undefined. If it is present navigate the user to home by using this.router.navigate(['home']);
Assuming you are using a token (like jwt) and localstorage, you can do something like this:
//This could be different, but you must save somewhere the token.
// It will depend on your startegy
// For example, when loggin in, you may save it on localstorage:
localStorage.setItem('currentUser', JSON.stringify(user)); // just an example.
//THEN, you can redirect using the router
this.router.navigate(['yourRoute']);
Hope that can help you! Please, tell me if you want a more detail example.

ReactJS - how to setup login pattern?

I'm sorry if this question is a bit vague, but I'm tackling this problem for the first time and any pointer would be useful.
I am building a web app using ReactJS and I need a login system - first page with two fields username / password and submit button. The server returns a token (1234) and this needs to be used in an auth header (Authorization: Bearer 1234) in order to access the protected area.
How should I handle the login and make the browser update itself with the new content available after login?
As the others have pointed out, it is a good idea to use React-Router.
I think you can use pattern like this: You get user inputs and send them via AJAX (with JQuery, Superagent, whatever you want). If the input is valid and user authenticated, the server sends back token with some user info, which can include his roles or permissions. Based on these received data, you can use React-Router to render other component, e.g. welcome page (by calling replaceState on React-Router history object - in flux action for example).
Additionally, you should save this token in a cookie or into a session/local storage (in order to be able to use it on every subsequent request), and the user info could be stored in a Flux store. After saving this user the store emits change event, which should lead to rerender of your root component with the user information you got.
Then, based on the new user roles or permissions in your store, you can have for example ES7 decorator on some of your components deciding, if it displays the actual component or not.
Hope it helps you a bit.

Categories