how can ı handle react with firebase authentication problem? - reactjs

I am trying develop user authentication page in react with firebase.
I can sign in but then sign in doesn't change to sign out.
what is the problem?
const handleAuthentication = () => {
if(user){
auth.signOut();
}
}
<div onClick={handleAuthentication}
className="header_option">
<span
className="header_optionLineOne" >Hello, Guest</span>
<span
className="header_optionLineTwo" >{user ?
'Sign Out': 'Sign In'}</span>
</div>

Probably the user is actually signed out, but the UI is not rerendering as it doesn't know about the change.
To fix this, you'll want to store the user in the component's state, with either setState or a useState hook:
const [user, setUser] = useState(null);
auth.onAuthStateChanged((user) => {
setUser(user);
});
With the user being part of the state, the call to setUser(user) will cause the component to rerender and thus show the updated (lack of) user information.
Also see the first code snippet in the Firebase documentation on getting the current user.

Related

Do I need to store isUserSignIn for componet rendering in Local Storage(React,Next,Firebase Auth)

(Firebase Google Signin + React(Next) )
If user sign in , setState to true.
And render the home component and welcome(login) component in index.js by state value.I made an application by storing that state in local storage and I think it is not a good practice. So if I don't use local storage there is a issue when user signed in and it should reach the home component but , user can also see welcome component before home component.
Logic index.js -> if userSignin (Home) : (Login)
Conditional Rendering
{isSignin ? (<>Home Component</>) : (<Welcome Component/>)}
state
const [isSignin, setisSignin] = useState(false);
changing state if user signin
useEffect(() => {
onAuthStateChanged(auth, (user) => {
if (user) {
setisSignin(true);
console.log(user);
}else {
setisSignin(false);
}
});
}, []);
firebase auto use localstorage when u signin an account. please check it in your browser localstorage. You don't need to store it by yourself. Then, when user revisit that website from the same web browser, firebase auto login (unless he did not logout). However, that auto login needs some amount of time. you need to do something during that amount of time. after that time, isSignIn will be true. I suggest something like this.
const [isSignIn, setSignIn] = useState(null);
useEffect(()=> listener_to_authstate_change() ,[])
if (isSignIn === null) return null; // something you like to show example - <Loading />
if (isSignIn === false) return <SignIn Component />
if (isSignIn === true) return <Home Component />

React Firebase UseEffect Firestore

I've got a user bar component directly adjacent to my navbar, showing avatar and display name (user details saved within a userid-named doc). I followed the firestore documentation for real time updates. Placed inside a use effect hook, which has a dependency array, but is firing repetitively, firing off about 4,000 calls a minute per logged in user).
I really just want the snapshot to update when a user updates their display name or avatar. (found on a different form component)
I console logged every useEffect hook in my project to narrow it down to this component. Is there something about the dependency array causing this? Is there a better way to write this? Thanks!
export default function UserBar() {
const { user } = useAuthContext()
const [me, setMe] = useState([])
useEffect(() => {
//user real-time subscription for avatar and displayname
const auth = getAuth()
const fireUser = auth.currentUser
const unsub = onSnapshot(doc(db, "users", fireUser.uid), (doc) => {
if (doc.exists()) {
setMe(doc.data())
console.log('looking for duplicate - userbar unsub')
} else {
console.log("No such document!")
}
})
return () => unsub()
}, [me])
return (
<>
{user && (
<div className="user-bar">
<p className="oneHunid">Welcome
<span className="bold"> {user.displayName}!</span>
</p>
<Avatar src={me.photoURL} />
</div>
)}
</>
)
}
You do not want to have [me] as a dependency when inside the useEffect() you call setMe(). That leads to an infinite loop:
me gets a new value, so render
me has a new value, so run useEffect()
useEffect() calls setMe()
go to # 1
Based on the above, it looks like what you really want is to have your useEffect() be dependent on the value of auth.currentUser. So get that value outside of the useEffect() and then check to be sure it is not null. If it is not null, then start the onSnapshot() listener.
BTW: if it would be of help, check out the user profiles with Firebase Auth project I developed. In particular, check out the FirebaseProvider.js which is where I configure the Firebase project and get all of its services, and AuthProvider.js which provides login, logout, registration and "user profile".

Local Storage values not getting loaded in React App

I am new to React and following one of the video series available on Udemy (React for the rest of us by Brad Schiff). The author has provided a backend system for user login etc.
When the user logs in, the backend server sends 3 values in response to a successful login: the login token, the user name and the avatar url (a dummy image from gravatar.com). These values are then stored in local storage from where they can be displayed on the UI:
const response = await axios.post("http://localhost:8080/login", {username, password});
if (response.data) {
// if response contains token, set login flag to true
props.loginFlagHandler(true);
// save user token, username, avatar in localstorage
localStorage.setItem("username", response.data.username);
localStorage.setItem("loginToken", response.data.token);
localStorage.setItem("avatar", response.data.avatar); }
Now, when I log in and the UI updates, the values received from server are successfully stored in local storage of my browser, but they are not getting reflected on the UI. The avatar image doesn't load and the Welcome message that should display the username doesn't work as expected (see the 1st image below). The Welcome message should read "Hello <username>, your feed is empty"
However, once I hit refresh, both the Avatar Image and the User name get displayed as they should, on their relevant place. (refer 2nd image).
In both the cases, I am referring to the localStorage variable as below:
<img className="small-header-avatar" src={localStorage.getItem("avatar")} />
And:
<h2 className="text-center">
Hello <strong>{localStorage.getItem("username")}</strong>, your feed is empty.
</h2>
I think this should be a noob thing that I'm missing here. Nevertheless, thanks in advance:
In React, when a component mounts
states are load
UI prints with the initial states
Lifecycle hooks run (e.g. useEffect) and update states
DOM re-prints with updated states
if you don't use state in your component then you should follow the above workflow to update your UI. Though I don't know what your props.loginFlagHandler(true) does, I am giving an example below.
const [isDataStored, setIsDataStored] = useState(false)
useEffect(() => {
const fetchData = async () => {
const response = await axios.post("http://localhost:8080/login", {username, password});
if (response.data) {
// if response contains token, set login flag to true
props.loginFlagHandler(true);
// save user token, username, avatar in localstorage
localStorage.setItem("username", response.data.username);
localStorage.setItem("loginToken", response.data.token);
localStorage.setItem("avatar", response.data.avatar);
}
setIsDataStored(true)
}
}, [])
you can also try lazy loading your child component.
Well you should use state like this.
const [avatar, setAvatar] = useState("");
const [username, setUsername] = useState("");
useEffect(() => {
setUsername(localStorage.getItem("username"))
setAvatar(localStorage.getItem("avatar"))
})
................
<img className="small-header-avatar" src={avatar} />
And:
<h2 className="text-center">
Hello <strong>{username}</strong>, your feed is empty.
</h2>

How to wait for auth state to load on the client before fetching data

Recently I stumbled across the useAuth and useRequireAuth hooks: https://usehooks.com/useRequireAuth/. They are incredibly useful when it comes to client-side authentication. However, what's the correct way for waiting until auth data is available to fetch some other data? I've come up with the following code:
const Page = () => {
// makes sure user is authenticated but asynchronously, redirects if not authenticated, short screen-flash
useRequireAuth()
// actual user object in state, will be updated when firebase auth state changes
const user = useStoreState((state) => state.user.user);
if (!user) {
return <div>Loading</div>
}
useEffect(() => {
if (user) {
fetchSomeDataThatNeedsAuth();
}
}, [user]);
return (
<h1>Username is: {user.name}</h1>
)
}
Is this a "good" way to do it or can this be improved somehow? It feels very verbose and needs to be repeated for every component that needs auth.
This looks fine to me. The thing you could improve is that your useRequireAuth() could return the user, but that's up to you.
Additionally, you probably should check if user is defined before rendering user.name.

Firebase Reactjs get current user from context

I'm new of Reactjs and I'd like to understand if the only way to get Firebase currentUser from context is through onAuthStateChanged.
I try to be more clear: let's say I signed-in by a "SignIn" component by using Firebase context and, after signed-in, I need to get currentUser in a different component, it seems to me the only way to get it is something like:
const [user, setUser] = useState(null);
...
useEffect(() => {
props.firebase.auth.onAuthStateChanged(authUser => {
if (!!authUser) {
setUser(authUser);
}
});
}, []);
Is it true?
Thanks
You can call on a current user any time
You can use this auth function
const user = firebase.auth().currentUser;
You don't have to store it. Unless you want to.
Thanks to who reply my question, I found the answer in this detailed article.

Resources