I am trying to learn to work with custom Hooks in React-native. I am using AWS Amplify as my backend, and it has a method to get the authenticated user's information, namely the Auth.currentUserInfo
method. However, what it returns is an object and I want to make a custom Hook to both returns the part of the object that I need, and also abstract away this part of my code from the visualization part. I have a component called App
, and a custom Hook called useUserId
. The code for them is as follows:
The useUserId
Hook:
import React, { useState, useEffect } from "react";
import { Auth } from "aws-amplify";
const getUserInfo = async () => {
try {
const userInfo = await Auth.currentUserInfo();
const userId = userInfo?.attributes?.sub;
return userId;
} catch (e) {
console.log("Failed to get the AuthUserId", e);
}
};
const useUserId = () => {
const [id, setId] = useState("");
const userId = getUserInfo();
useEffect(() => {
userId.then((userId) => {
setId(userId);
});
}, [userId]);
return id;
};
export default useUserId;
The App
component:
import React from "react";
import useUserId from "../custom-hooks/UseUserId";
const App = () => {
const authUserId = useUserId();
console.log(authUserId);
However, when I try to run the App component, I get the same Id written on the screen twice, meaning that the App
component is executed again.
The problem with this is that I am using this custom Hook in another custom Hook, let's call it useFetchData
that fetches some data based on the userId, then each time this is executed that is also re-executed, which causes some problems.
I am kind of new to React, would you please guide me on what I am doing wrong here, and what is the solution to this problem. Thank you.
CodePudding user response:
The issue is likely due to the fact that you've declared userId
in the hook body. When useUserId
is called in the App
component it declares userId
and updates state. This triggers a rerender and userId
is declared again, and updates the state again, this time with the same value. The useState
hook being updated to the same value a second time quits the loop.
If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects. (React uses the Object.is comparison algorithm.)
Either move const userId = getUserInfo();
out of the useUserId
hook
const userId = getUserInfo();
const useUserId = () => {
const [id, setId] = useState("");
useEffect(() => {
userId.then((userId) => {
setId(userId);
});
}, []);
return id;
};
or more it into the useEffect
callback body.
const useUserId = () => {
const [id, setId] = useState("");
useEffect(() => {
getUserInfo().then((userId) => {
setId(userId);
});
}, []);
return id;
};
and in both cases remove userId
as a dependency of the useEffect
hook.
CodePudding user response:
Replace userId.then with to getUserId().then. It doesn't make sense to have the result of getUserId in the body of a component, since it's a promise and that code will be run every time the component renders.