Firebase `displayName` returns Null - React JS - javascript

I use React js Material UI, when I call currentUser.displayName it returns null and when I call currentUser.email it works fine for me.
Here's the function to register a new account to firebase and to update the displayName value from a textFiled which is firstName and lastName :
const firstNameRef = useRef();
const lastNameRef = useRef();
const emailRef = useRef();
const passwordRef = useRef();
const registerHandler = async (e) => {
e.preventDefault();
const firstName =
firstNameRef.current.value.charAt(0).toUpperCase() +
firstNameRef.current.value.slice(1);
const lastName =
lastNameRef.current.value.charAt(0).toUpperCase() +
lastNameRef.current.value.slice(1);
const fullName = `${firstName} ${lastName}`;
const email = emailRef.current.value;
const password = passwordRef.current.value;
// password verification
if (password.length < 6) {
setPasswordError("Password must be at least 6 digits!");
return;
}
// create account
try {
setLoading(true);
setIsError("");
setEmailError("");
setPasswordError("");
await register(email, password)
.then((response) => {
response.user.updateProfile({
displayName: fullName,
});
setIsError("");
setEmailError("");
setPasswordError("");
})
.catch((error) => {
setEmailError(
"The email address is already in use by another account."
);
});
} catch {
setIsError("Error Creating your Account!");
}
setLoading(false);
setSnackBarOpen(true);
};
and here's context code which wraps the app component:
const AuthContext = createContext(null);
export const AuthProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState();
const [loading, setLoading] = useState(true);
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
setCurrentUser(user);
setLoading(false);
});
return unsubscribe;
}, []);
const login = async (email, password) => {
await auth.signInWithEmailAndPassword(email, password);
};
const register = async (email, password) => {
await auth.createUserWithEmailAndPassword(email, password);
};
const logout = async () => {
await auth.signOut();
};
const resetPassword = async (email) => {
await auth.sendPasswordResetEmail(email);
};
return (
<AuthContext.Provider
value={{ currentUser, login, register, logout, resetPassword }}
>
{!loading && children}
</AuthContext.Provider>
);
};
export const useAuth = () => {
return useContext(AuthContext);
};
and here's my first name & last name TextFields in JSX:
<TextField
fullWidth
label="First Name"
disabled={loading}
type="text"
required
inputRef={firstNameRef}
/>
<TextField
fullWidth
disabled={loading}
label="Last Name"
type="text"
required
inputRef={lastNameRef}
/>

Looks like the problem is here:
const register = async (email, password) => {
await auth.createUserWithEmailAndPassword(email, password);
};
You are not returning the response from here so you should do this instead:
const register = async (email, password) => {
return await auth.createUserWithEmailAndPassword(email, password);
};

Related

i have to click on the button twice to post data to api in react

I have console.log(ed) the values while executing and what happens is on the first click, inputValue is sent with a null string to api, then on the next click the inputValue with string is sent to api. I have already changed the value of inputValue using the setter function in input tag with onChange function and then i have called the api so How do i fix it so it sends it on the first click.
const InputEmail = () => {
const navigate = useNavigate()
const [inputValue, setInputValue] = useState('')
const [apiData, setApiData] = useState('')
const [isError, setIsError] = useState(false)
// useEffect(() => {
// //API()
// }, [])
const API = () => {
console.log(inputValue)
axios
.post(url, {
email: inputValue
})
.then((response) => {
setApiData(response.data)
})
console.log(apiData.is_active)
}
const handleSubmit = () => {
API()
if(apiData.is_active) {
localStorage.setItem('email',inputValue)
navigate("/assessment")
} else {
setIsError(true)
}
}
return (
<div className='main'>
<FormControl>
<h2 className='text'>Registered Email address</h2>
<Input id='email' type='email' value={inputValue} onChange={e => setInputValue(e.target.value)}/>
{
isError ? <FormHelperText color='red'>Email not found. Please enter registered email</FormHelperText> : null
}
<Button
mt={4}
colorScheme='teal'
type='submit'
onClick={handleSubmit}
>
Submit
</Button>
</FormControl>
</div>
)
}
You must wait for your axios to fetch data from the url before making a handle. It will work if you await untill your async API() functions brings data.
const API = () => {
return axios.post(url, {
email: inputValue,
});
};
const handleSubmit = async () => {
const response = await API();
if (response.data.is_active) {
localStorage.setItem("email", inputValue);
navigate("/assessment");
} else {
setIsError(true);
}
};

how to verify user email in firebase react native(Expo)

In my application user authentication is done every thing is working fine but I want implement user email verification feature in my app I am done with user authentication and storing user details in Firestore
my signup method code :
const onRegister = async (email, password, username) => {
try {
const authUser = await firebase
.auth()
.createUserWithEmailAndPassword(email, password);
db.collection("users").add({
owner_uid: authUser.user.uid,
displayname: username,
email: authUser.user.email,
photoURL: await getrandompicture(),
});
await firebase.auth().currentUser.updateProfile({
displayName: username,
photoURL: await getrandompicture(),
});
} catch (error) {
Alert.alert(error.message);
}
};
my authnavigation :
const Authnavigation = () => {
const [currentUser, setcurrentUser] = useState(null);
const userHandler = (users) =>
users ? setcurrentUser(users) : setcurrentUser(null);
useEffect(
() => firebase.auth().onAuthStateChanged((user) => userHandler(user)),
[]
);
return (
<>
{currentUser ? (
<Singninstack userID={currentUser.uid} />
) : (
<Signoutstack />
)}
</>
);
};
export default Authnavigation;
You can call sendEmailVerification right after creating the user.
await authUser.user.currentUser.sendEmailVerification()
.then(() => {
// Email verification sent!
// ...
});

React native context api not passing value properly, null is not an object (evaluating 'user.uid')

I want to retrieve a field value of a document in Users collection by referencing it via the where condition from Firestore. I use the context api to pass the user object of the logged in user in my app. I get this error that user.uid is null. I can't spot where the mistake is. I have added the relevant piece of code.
EditProfile.js
const EditProfile = () => {
const { user } = React.useContext(AuthContext);
const [name, setName] = React.useState();
React.useEffect(() => {
const userid = user.uid;
const name = getFieldValue("Users", userid);
setName(name);
}, []);
};
export default EditProfile;
passing and getting value via context
export const AuthContext = React.createContext();
export const AuthProvider = ({ children }) => {
const [user, setUser] = React.useState(null);
return (
<AuthContext.Provider
value={{
user,
setUser,
}}
>
{children}
</AuthContext.Provider>
);
};
const AppStack = () => {
return (
<AuthProvider>
<BottomTab.Navigator>
<BottomTab.Screen
name="ProfileStack"
component={ProfileStack}
/>
</BottomTab.Navigator>
</AuthProvider>
);
};
export default AppStack;
ProfileStack.js
export const ProfileStack = ({ navigation }) => {
return (
<Stack.Navigator>
<Stack.Screen
name="Profile"
component={Profile}
/>
<Stack.Screen
name="EditProfile"
component={EditProfile}
/>
</Stack.Navigator>
);
};
getFieldValue function
export const getFieldValue = (collection, userid) => {
firestore()
.collection(collection)
.where("userid", "==", userid)
.get()
.then((querySnapshot) => {
if (querySnapshot.size === 0) {
return "";
}
if (querySnapshot.size === 1) {
const { name } = querySnapshot[0].data();
return name;
}
})
.catch((e) => console.log(e));
};
Routing file
const Routes = () => {
// Set an initializing state whilst Firebase connects
const [initializing, setInitializing] = React.useState(true);
const { user, setUser } = React.useContext(AuthContext);
// Handle user state changes
const onAuthStateChanged = (user) => {
setUser(user);
if (initializing) setInitializing(false);
};
React.useEffect(() => {
RNBootSplash.hide();
const subscriber = auth().onAuthStateChanged(onAuthStateChanged);
return subscriber; // unsubscribe on unmount
}, []);
if (initializing) return null;
return (
<NavigationContainer>
{user ? <AppStack /> : <AuthStack />}
</NavigationContainer>
);
};
export default Routes;

When I register I cannot see the user name until I refresh or login

when I register it take me to the dashboard page where there is a welcome note with user name but the issue is I cannot see the user name until I refresh or login again. I am sharing both my registration action.js code and my dashboard
my registration.js code
const Register = (props) => {
const { classes } = props
const [name, setName] = useState('')
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const dispatch = useDispatch();
const onRegister = async () => {
dispatch(startRegister(name, email, password));
props.history.push('/dashboard')
}
action.js
export const startRegister = (name, email, password) => {
// const { name, email, password } = props
return () => {
return firebase.auth().createUserWithEmailAndPassword(email, password)
.then((currentUser) => {
// Signed in
const user = firebase.auth().currentUser;
user.updateProfile({
displayName: name,
}).then(function () {
console.log('Updated');
// Update successful.
}).catch(function (error) {
// An error happened.
console.log(error);
});
// history.push('/dashboard')
// ...
})
.catch((error) => {
var errorMessage = error.message;
console.log(errorMessage);
// ..
});
};
};
dashboard.js
const Dashboard = props => {
const { classes } = props
const onSignout = async (e) => {
await firebase.auth().signOut()
//props.history.push('/')
}
const username = useSelector(state => state.auth.name);
return (
<main className={classes.main}>
<Paper className={classes.paper}>
<Typography component="h1" variant="h5">
{`Welcome User ${username ? username : ''}`}
At a glance I belive the issue is because of javascript promises, firebase.auth().createUserWithEmailAndPassword is an asynchronous function.
Try this
In registration.js
const onRegister = async () => {
const userData = {name, email, password}
dispatch(startRegister(props, userData));
}
In action.js
export const startRegister = (props, userData) => {
const { name, email, password } = userData;
return () => {
return firebase.auth().createUserWithEmailAndPassword(email, password)
.then((currentUser) => {
// Signed in
const user = firebase.auth().currentUser;
user.updateProfile({
displayName: name,
}).then(function () {
console.log('Updated');
// Navigate to dashboard after data is been saved
props.history.push('/dashboard');
}).catch(function (error) {
// An error happened.
console.log(error);
});
})
.catch((error) => {
var errorMessage = error.message;
console.log(errorMessage);
// ..
});
};
};

Using the Context API gives me undefined

So I'm using Auth0 for my user sign up. I'm trying to get the user id under sub:value to add to my database to identify with the post of a user. I'm trying to use a Context API in order to get the user info to put in my database.
react-auth0-spa.js
// src/react-auth0-spa.js
import React, { useState, useEffect, useContext } from "react";
import createAuth0Client from "#auth0/auth0-spa-js";
const DEFAULT_REDIRECT_CALLBACK = () =>
window.history.replaceState({}, document.title, window.location.pathname);
export const Auth0Context = React.createContext();
export const useAuth0 = () => useContext(Auth0Context);
export const Auth0Provider = ({
children,
onRedirectCallback = DEFAULT_REDIRECT_CALLBACK,
...initOptions
}) => {
const [isAuthenticated, setIsAuthenticated] = useState();
const [user, setUser] = useState();
const [auth0Client, setAuth0] = useState();
const [loading, setLoading] = useState(true);
const [popupOpen, setPopupOpen] = useState(false);
useEffect(() => {
const initAuth0 = async () => {
const auth0FromHook = await createAuth0Client(initOptions);
setAuth0(auth0FromHook);
if (window.location.search.includes("code=") &&
window.location.search.includes("state=")) {
const { appState } = await auth0FromHook.handleRedirectCallback();
onRedirectCallback(appState);
}
const isAuthenticated = await auth0FromHook.isAuthenticated();
setIsAuthenticated(isAuthenticated);
if (isAuthenticated) {
const user = await auth0FromHook.getUser();
setUser(user);
}
setLoading(false);
};
initAuth0();
// eslint-disable-next-line
}, []);
const loginWithPopup = async (params = {}) => {
setPopupOpen(true);
try {
await auth0Client.loginWithPopup(params);
} catch (error) {
console.error(error);
} finally {
setPopupOpen(false);
}
const user = await auth0Client.getUser();
setUser(user);
setIsAuthenticated(true);
};
const handleRedirectCallback = async () => {
setLoading(true);
await auth0Client.handleRedirectCallback();
const user = await auth0Client.getUser();
setLoading(false);
setIsAuthenticated(true);
setUser(user);
};
return (
<Auth0Context.Provider
value={{
isAuthenticated,
user,
loading,
popupOpen,
loginWithPopup,
handleRedirectCallback,
getIdTokenClaims: (...p) => auth0Client.getIdTokenClaims(...p),
loginWithRedirect: (...p) => auth0Client.loginWithRedirect(...p),
getTokenSilently: (...p) => auth0Client.getTokenSilently(...p),
getTokenWithPopup: (...p) => auth0Client.getTokenWithPopup(...p),
logout: (...p) => auth0Client.logout(...p)
}}
>
{children}
</Auth0Context.Provider>
);
};
other.js (trying to get user info from react-auth0-spa.js)
class AddAlbum extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
let value = this.context;
console.log(value);
}
render() {
return (
)
}
AddAlbum.contextType = Auth0Context;
This gives me user: undefined
In my index.js I have this
ReactDOM.render(
<Auth0Provider
domain={config.domain}
client_id={config.clientId}
redirect_uri={window.location.origin}
onRedirectCallback={onRedirectCallback}
>
<App />
</Auth0Provider>,
document.getElementById("root")
);
Which I believe is giving me these results:
So I'm wondering why my Context API isn't working and giving me user: undefined.
You're logging the user when the component first mounts, which is long before the await auth0FromHook.getUser() call will complete. Log it in a componentDidUpdate, or check in a parent if that value is available, and don't mount the child component until it is.

Categories

Resources