I am creating a front end for an API in react native. For signed authentication, I use the FireBase service. Everything is good, However, I have a problem. I want after creating the user, my program stays on the login screen and when on the login screen provide the credential, it should move to the Home screen.
In my case, it navigates to the login screen and then use effect () activate and it navigates to the Home. How can I stay in HomeScreen?
// Registrationscreen
const handleSignUp = () => {
createUserWithEmailAndPassword( auth,email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
// ...
})
.then( navigation.dispatch(
StackActions.replace('Login', {
user: 'jane',
})
))
.catch((error) => alert(error.message));
};
//logIn Screen
const LoginScreen = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const navigation = useNavigation();
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
if (user) {
navigation.replace("Home");
}
});
return unsubscribe;
}, []);
const handleLogin = () => {
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
// ...
})
.catch((error) => alert(error.message));
};
I wanted that after registration of the new user, it should navigate to the login page and Stay there and when we put in the credential and press logIn then it should navigate to the Home Screen.
There's unfortunately a lot of places this could be going wrong but it looks like there's a pretty serious error in your LoginScreen component - the useEffect is only running when the component initially renders. This means that by the time the handleLogin function is called the useEffect doesn't know that it needs to run again - which means the redirect to the home screen never runs.
To temporarily fix this: create a user object in state. When the user gets returned from signInWithEmailAndPassword you can store the user into state. Reminder you'd need to update your dependency array in the useEffect to include the user object.
Related
I am using Firebase Realtime Database for a site I am developing with React. In a useEffect method, I am using Firebase's get method to receive all the data from the database and it works when I switch from the home page back to the page I am displaying the data on but it doesn't work when I refresh my page. I have tried using an async await function, console.logging everything I could think of, and re-writing the entire code.
This is my useEffect method that fetches an input that was previously saved to the database. If I switch from the 'Journal' Router page to Home page and back, it loads correctly but it doesn't load correctly if I refresh the page. When I refresh, it console.logs 'No Data' but I know the data exists because when I switch between router pages it does load.
useEffect(() => {
const dbRef = ref(getDatabase())
//Fetches dreams from firebase's database
get(child(dbRef, `/${user.uid}/dreams`)).then(snapshot => {
if (snapshot.exists()){
const dreams = snapshot.val()
Object.values(dreams).forEach(dream => {
setUserDreams(prev => [...prev, dream])
})
} else {
console.log('No Data')
}
}).catch(err => {
console.error(err);
})
...
}, [])
The JSON structure of the database is basically this
"USER_ID" : {
"dreams" : [{"RANDOM_UUID" : {...}}],
"tags" : [{"RANDOM_UUID" : {...}}]
}
The user ID is the uid that firebase generates in their user authentication feature and it doesn't change and the random uuid is a random string generated from the firebase uuidv4 method.
This is how the user variable is populated:
import {createContext, useContext, useEffect, useState} from 'react'
import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
updateProfile,
onAuthStateChanged
} from 'firebase/auth';
import { auth } from '../firebase-config';
const UserContext = createContext();
export const AuthContextProvider = ({children}) => {
const [user, setUser] = useState({})
const createUser = (email, password) => {
return createUserWithEmailAndPassword(auth, email, password);
}
const updateUsername = (username) => {
return updateProfile(auth.currentUser, {
displayName: username
})
}
const signIn = (email, password) => {
return signInWithEmailAndPassword(auth, email, password);
}
const logout = () => {
return signOut(auth);
}
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
console.log(currentUser)
setUser(currentUser)
})
return () => {
unsubscribe()
}
}, [])
return (
<UserContext.Provider value={{createUser, user, logout, signIn, updateUsername}}>
{children}
</UserContext.Provider>
)
}
export const UserAuth = () => {
return useContext(UserContext)
}
Sorry if this is a bit weird but I figured out the issue. After logging the user variable in my journal file, I learned that it isn't populated until after that useEffect is ran so I just put user as the dependency variable in my useEffect hook so it waits until it is populated to run that hook.
useEffect(() => {
const dbRef = ref(getDatabase())
//Fetches dreams from firebase's database
get(child(dbRef, `/${user.uid}/dreams`)).then(snapshot => {
if (snapshot.exists()){
const dreams = snapshot.val()
Object.values(dreams).forEach(dream => {
setUserDreams(prev => [...prev, dream])
})
} else {
console.log('No Data')
}
}).catch(err => {
console.error(err);
})
...
}, [user])
This is what worked, the only thing changed was the dependency array. Meaning, the user variable was populated after the useEffect hook ran which is what made me have issues. Thanks for the commenter that helped me out!
I have integrated the #react-native-firebase/auth package for user authentication. On the 'onAuthStateChanged' listener the user object is null without calling the signout. Are there any possible fixes for this?
I resolved same issue. But in React application 🙃
It's happened because u need to wait, before firebase-auth get authenticated user. So, you can create useState with default loading in true position. And while it's loading - display spinner or something else. When user will be load - setLoading to false with useEffect.
My app.js:
const [loading, setLoading] = useState(true);
const [user, setUser] = useState(null);
useEffect(() => {
onAuthStateChanged(auth, (authorizedUser) => {
if (authorizedUser) {
console.log('success sign-in')
setUser(authorizedUser);
setLoading(false);
}
});
}, []);
I have React pages (BlogContent & RelatedBlog),
When a user views blog content, he can see below more blogs for the author. When the user clicks on the article he wants to read, the slug on Url changes but the content does not change until the user refreshes the page, so the user must refresh the page every time he wants to see all related blogs for the author.
I think the reason the blog page require refreshes every time is because useEffect() , but I don't know what is the trick to fix it
Here's my code to page BlogContent:
export const BlogContent = () => {
const { slug } = useParams();
const [data, setData] = useState({ posts: [] });
useEffect(() => {
axiosInstance.get(slug).then((res) => {
setData({ posts: res.data });
});
}, [setData]);
let AuthorBlog = data.posts.author
};
and here for RelatedBlog
export const RelatedBlog = (props) => {
const { AuthorBlog } = props;
const [appState, setAppState] = useState([]);
useEffect(() => {
axiosInstance.get("/").then((res) => {
const allBlogs = res.data;
setAppState(allBlogs);
});
}, [setAppState]);
const filterAuthor = appState.filter((item) => item.author === AuthorBlog) ;
Thanks
As I've written in the comments - adding slug to the dependency array of your useEffect fixed the problem.
Why is that?
Dependency array in useEffect hook is used to rerun the hook when one of these variables changes. In your case, changing the url, changes the slug so the component should load new data.
I would even remove setData from this array, because it doesn't do anything as useState setters don't ever change.
useEffect(() => {
laxiosInstance.get(slug).then((res) => {
setData({ posts: res.data });
});
}, [slug]);
I have a react app that is needing to authenticate against a windows auth server. I am achieving this by hitting an endpoint to get my user details, with the credentials: include header. From my understanding, this should trigger the login prompt on chrome. However the prompt does not show until I either:
Hard refresh the page
Open devtools
Because it doesn't prompt a logon, the app shows as empty, because I'm returning null if its not authenticated.
How can I get chrome to actually prompt for logon details in the normal app view?
App.tsx
export const App: React.FC = () => {
const { isAuthenticated, login } = useAuth();
useEffect(() => {
if (!isAuthenticated) {
login();
}
}, [isAuthenticated, login]);
if (!isAuthenticated) {
return null;
}
return (
<div>App Content</div>
);
};
AuthProvider.tsx
export const AuthProvider: React.FC = ({ children }) => {
const [isLoading, setIsLoading] = useState<boolean>(true);
const [user, setUser] = useState<IUserDetail>();
const login = useCallback(() => {
setIsLoading(true);
UserApi.getMe()
.then(({ data }) => setUser(data))
.finally(() => setIsLoading(false));
}, []);
const logout = useCallback(() => {
setUser(undefined);
}, []);
return (
<AuthContext.Provider
value={{
user,
isAuthenticated: Boolean(user),
isLoading,
login,
logout,
}}
>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => useContext(AuthContext);
UserApi.ts
export const getMe = () => {
return axios.get<IUserDetail>("/api/users/me");
};
Axios interceptor logic, which sets the credentials header for every request
axios.interceptors.request.use((request) => {
request.headers["credentials"] = "include";
return request;
});
I had a fundamental misunderstanding. The authentication happens when the website is downloaded from the server - not when I make an API request.
The reason for why I wasn't getting the auth prompt was because I had a service worker that cached the files, so they weren't being requested from the server, thus no auth prompt.
I am able to login a user successfully using Firebase. In my code, after the user has successfully logged in, they are directed to their profile. My problem is that whenever I refresh the browser, the user is logged out for a split second and then directed back to their profile. If I'm on any other page, the user is completely logged out. I'm quite new to custom hooks and am trying to learn on the job. Here's my code
const [currentUser, setCurrentUser] = useState("")
const [currentUserData, setCurrentUserData] = useState("")
const [loading, setLoading] = useState(false)
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(user => {
if (user) {
setCurrentUser(user)
db.collection('users')
.doc(user.uid)
.get()
.then(doc => {
setCurrentUserData(doc.data())
// MUST REARANGE vvvv
history.push('/')
})
setLoading(false)
}
else {
setCurrentUser(null)
setCurrentUserData(null)
}
})
return unsubscribe
}, [history])