I want to be able to create a document with the user id once a user has signed up I found out that that best place to do this since it happens only once is when a user has signed up the issue here is it is a await function and the only place I get the user id is in then callback any idea how to syntax this..
const Signup = (email: string, password: string) => {
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
const docRef = doc(db, 'clients', user.uid);
const payload = { clients: [] };
async () => await setDoc(docRef, payload);
// ...
})
.catch((error) => {
const errorCode = error.code;
//const errorMessage = error.message;
console.log(errorCode);
if (errorCode === 'auth/weak-password') {
_miscContext.SetSnackBarMsg(true, 'password must be at least 6 charechters');
}
if (errorCode === 'auth/email-already-in-use') {
_miscContext.SetSnackBarMsg(true, 'email already exists');
}
});
};
The idea of .catch and .then methods is to return another Promise that can be chained.
You can just return it from the callback. If the returned type of the .then function is a Promise it will be ignored, otherwise, it will be transformed to the Promise, so that's why you can chain .then and .catch methods
Also, this question: should I always use asych / await:
Let's understand what is doing async and await keywords (you need to understand this, and you will get where and why you need to use them).
async - this is just converting your function to async function (you can add async to your function and change it to the Promsie`
here is the simple example
function example() { return 1; }
console.log(example()); // log: 1
with async
async function example() { return 1; }
console.log(example()); // log: PromiseĀ {<fulfilled>: 1}
// so if the async function is just converting your function to the promise, it means you can get the value by `.then` and `.catch` methods
await - only uses inside async function, and just waiting to the Promise completing and converting the promise to the response
// just dummy example
async function example() {
const responseOfPromise = await Promise.resolve(3);
return responseOfPromise;
}
Usage example of your actual function
const Signup = (email: string, password: string) => {
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
const docRef = doc(db, 'clients', user.uid);
const payload = { clients: [] };
return setDoc(docRef, payload)
})
.then((responseOfSetDocFunction) => {
// and here the callback argument will be returned value from previous then (returned value of setDoc function)
console.log(responseOfSetDocFunction);
})
.catch((error) => {
const errorCode = error.code;
//const errorMessage = error.message;
console.log(errorCode);
if (errorCode === 'auth/weak-password') {
_miscContext.SetSnackBarMsg(true, 'password must be at least 6 charechters');
}
if (errorCode === 'auth/email-already-in-use') {
_miscContext.SetSnackBarMsg(true, 'email already exists');
}
});
};
Related
I create this custom hook in my React app. It should return a boolean.
const useFetchResponse = (url: string) => {
const [isValid, setIsValid] = useState<boolean>(false);
useEffect(() => {
const fetchResponse = async () => {
const response = await fetch(url);
console.log(response);
const obj = await response.json();
if (response.ok) {
console.log(await response.json());
setIsValid(true);
}
return response;
};
fetchResponse().then((res) => res);
}, []);
return isValid;
};
export default useFetchResponse;
When I log const obj = await response.json(); it returns: {"keyName":"some=key"}.
How do I create a condition to check if response.json() has a key named keyName?
Is that for example console.log('keyName' in obj) // true?
Do you see more things which I can improve and refactor?
Let assume you get response as follow
let response = {
a:'data1',
b:'data2',
c:'data3'
};
Then you can extract keys from object as below:
let keyOnly = Object.keys(response)); // output will be ["a","b","c"]
then you can check if your require value includes on above array or not as below: Assuming if you want to check if "b" is included or not
let checkKey = keyOnly.includes(b)
if you want to check whether an object has a certain property or not, the in operator is fine.
const obj = { a: 1 };
'a' in obj // return true
'b' in obj // return false
About improvements
it's better to save all fetch states, not only valid or not. And you should wrap request with try/catch block. For example:
const [fetchState, setFetchState] = useState('pending');
useEffect(() => {
const fetchResponse = async () => {
try {
setFetchState('loading');
const response = await fetch(url);
console.log(response);
const obj = await response.json();
if (response.ok) {
console.log(await response.json());
setFetchState('success');
}
return response;
} catch (error) {
setFetchState('failed')
}
};
fetchResponse().then((res) => res);
}, []);
return fetchState;
};
fetchResponse(); would be enough. fetchResponse().then((res) => res); is unnecessary.
[optional] You could use libraries to making requests, like an axios. That would be more convenient.
in is slower than below way.
const isValid = obj[`keyname`] !== undefined
Check more detail in here
I saw similar threads on this but still can't be sure if I'm doing something wrong or the warning is misplaced.
I have a component with tryLogin function that calls an outer function:
export const Login: React.FunctionComponent<LoginProps> = ({ login }) => {
const navigate = useNavigate();
const tryLogin = async (payload: LoginPayload) => {
await login(payload); // This line gives the warning
navigate('./home');
};
The outer function is a class named 'login', in a store, on which I receive the warning. I'm using await here because I'd like to navigate only after login is done.
The class:
public login = async (payload: LoginPayload): Promise<void> => {
try {
const {
data: { accessToken },
} = await login({ payload });
this.authResponse = { accessToken };
console.log({ accessToken });
this.rootStore.main.setLoading(false);
} catch (err) {
this.rootStore.main.setLoading(false);
console.error('error', err);
}
};
The function returns a promise and I'm awaiting it inside tryLogin, so am I doing something wrong to receive this warning?
I have a problem with async request return. It returns me back a Promise instead of data!!
So i tried to process data variable a second time but it did not work. I exported it as it needs, created initial state for repo=[], passed in to the reducer...
gitContext.jsx
const getRepos = async (login) => {
setLoading();
const params = new URLSearchParams({
sort:'created',
per_page:10
})
const response = await fetch(`http://api.github.com/users/${login}/repos?${params}`)
if (response.status === 404) {
window.location = './notfound'
} else {
const data = await response.json();
console.log(data);
dispatch({
type: 'GET_REPOS',
payload: data
})
}
}
Here is the function call from User.jsx
const { getUser, user, isLoading, repos, getRepos } = useContext(GitContext);
const params = useParams()
useEffect(() => {
getUser(params.login);
// console.log(getRepos(params.login?.repos))
getRepos(login?.repos);
}, [])
According to the documentation from firebase you can get a document very simply by using get()
But for some reason in my code it always displays that there's no such document, even though it does exist, this is what I'm doing:
useEffect(() => {
console.log(user, "This is the user UID:"+user.uid)
const userDoc = db.collection('usuarios').doc(user.uid);
const doc = userDoc.get();
if (!doc.exists) {
console.log('No such document!');
}
else {
userDoc
.onSnapshot(snapshot => {
const tempData = [];
snapshot.forEach((doc) => {
const data = doc.data();
tempData.push(data);
});
setUserData(tempData);
})
}
}, [user]);
This is what the console.log() shows:
This is how it looks in firebase:
const doc = userDoc.get();
if (!doc.exists) {
.get returns a promise, so you're checking the .exists property on a promise, which is undefined. You will need to wait for that promise to resolve, either with .then:
userDoc.get().then(doc => {
if (!doc.exists) {
// etc
}
});
Or by putting your code in an async function and awaiting the promise:
const doc = await userDoc.get();
if (!doc.exists) {
// etc
}
If you're using the firebase 8 web version, the userDoc.get() returns a promise, not the document:
userDoc.get().then((doc) => {
if (!doc.exists) {
console.log('No such document!');
} else {
const tempData = [];
const data = doc.data();
tempData.push(data);
setUserData(tempData)
console.log('it worked')
}
}).catch((error) => {
console.log("Error getting document:", error);
});
You can get more info about promises in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises.
In your code you are using the get method to fetch user data and get doesn't provide a snapshot. also, you missed that get() will return a promise so you have to handle using async-await or .then etc.
useEffect(() => {
console.log(user, "This is the user UID:"+user.uid);
getUser(user.uid).then(userData => {
setUserData(userData);
});
}, [user]);
const getUser = async (id) => {
try {
const user = await db.collection('usuarios').doc(id).get();
const userData = user.data();
return userData;
} catch (err){
console.log('Error during get user, No such document!');
return false;
}
I am new to reactJS , my problem is that I want to assign my varaiable a value that has been returned from a axios function.When I do this, I get undefined value for u1.
function getUsername(userid){
var user = ''
axios.post('/api/getuserdata' , {_id:userid}).then(res=>{
console.log(res.data)
const userdata = res.data[0]
user = userdata.username
}).catch(err=>{
console.log(err)
})
return user
}
const u1 = getUsername(id)
The reason your code doesn't work is that the POST request handled by axios is async, your getUsername function won't wait for that request to resolve and return user immediately after it's called.
The simplest solution is that make your getUsername async and call it in another async function, or if you want to use the result returned from POST request for some other stuff, you can store it as state in React, it would be better.
You can use something like this:
const getUsername = async (userid) => {
try {
const response = await axios.post("/api/getuserdata", { _id: userid });
const userdata = response?.data?.[0]?.username || "";
return userdata;
} catch (error) {
console.log(`error`, error);
}
};
// in another function
const doSomethingWithUsername = async (id) => {
const username = await getUsername(id);
// other stuff..
}
async function getUsername(userid) {
try {
const result = await axios.post('/api/getuserdata' , {_id:userid});
const user = result.data;
}
catch (error) {
console.log(error)
}
}