In my recent project, I encountered an interesting challenge that I’m sure many of you have faced—fetching data based on user roles in a React Native app.
I’d added user roles (regular, admin) to my app, and as an admin, I needed to fetch all jobs in the system.
The logic to do this was simple—check the logged-in user’s role and fetch data accordingly. But what I didn’t expect was how React’s asynchronous behavior would impact my logic.
Here's the initial code snippet I was working with:
const [loggedInUser, setLoggedInUser] =
useState<Partial<User> | null>(null);
const fetchJobs = async () => {
try {
let firebaseService = await new FirebaseService();
let jobsList: Job[] = [];
if (loggedInUser?.role == UserRoles.ADMIN)
jobsList = await firebaseService.listAllJobs();
else
jobsList = await firebaseService.listSingleUserJob();
setJobs(jobsList);
setFilterJobs(jobsList);
} catch (error) {
console.error('Error fetching jobs:', error);
} finally {
setRefreshing(false);
setIsLoading(false);
}
};
useEffect(() => {
const fetchUser = async () => {
try {
let user = await returnLoggedUser();
setLoggedInUser(user);
} catch (error) {
console.error('Failed to fetch user', error);
}
};
fetchUser();
}, []);
useFocusEffect(
useCallback(() => {
if (!hasRun) {
fetchJobs();
setHasRun(true);
}, []
);
UseFocusEffect runs when the screen gains the focus.
In theory, it made sense. But what I wasn’t ensuring was that loggedInUser would always be defined before I tried to fetch jobs. Because useEffect and useFocusEffect run asynchronously, there was no guarantee that loggedInUser would be set by the time fetchJobs() ran
That's how this react's asynchronous behavior comes into picture.
I needed to ensure that loggedInUser had been set before proceeding with the job-fetching logic.
By adding a check for loggedInUser, I made sure that fetchJobs only runs when the user information is available:
useFocusEffect(
useCallback(() => {
if (loggedInUser && !hasRun) {
fetchJobs();
setHasRun(true);
}, [loggedInUser]
);
Keep Building!
Top comments (0)