DEV Community

amanbhoria
amanbhoria

Posted on

Handling Asynchronous State with User Roles in React Native with Firebase

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);
      }, []
  );
Enter fullscreen mode Exit fullscreen mode

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]
  );
Enter fullscreen mode Exit fullscreen mode

Keep Building!

Top comments (0)