How to return errors from Zustand Store

Viewed 528

I'm using Zustand for a React Native project, and I'm not used to this setup. I have a store with some variables and functions, and I can't get Zustand to return error values for form entries.

Here is my store:

import create from 'zustand';
import auth from '@react-native-firebase/auth';

export interface UserType {
  uid: string
  displayName?: string
  email?: string
}

export interface UserStoreType {
  user: UserType | null,
  login: (email: string, password: string) => void,
  logout: () => void,
}

const UserStore = create<UserStoreType>(set => ({
    user: null,
    login: async (email: string, password: string) => {
      auth().signInWithEmailAndPassword(email, password)
        .then(res => {
          set(state => {
            return {
              ...state,
              user: {
                uid: res.user.uid
              }
            }
          }, true)
        })
        .catch((e) => {
          console.log('error: ', e)
          return new Error(e);
      })
    },
    logout: async () => {
      set(state => {
        return {
          ...state,
          user: null
        }
      })
    },
    updateUserAuth: async (user: UserType) => {

    }
  })
)

export default UserStore;

Here is my login function:

const handleLogin = async () => {
    if (!formData.email || !formData.password) {
      if (!formData.email) setErrors(prev => ({...prev, email: 'Error with email'}));
      if (!formData.password) setErrors(prev => ({...prev, password: 'Error with password'}))
      return
    }
    try {
      login(formData.email, formData.password)
    } catch(e) {
      console.log('catch running')
      console.log('Error in Login.tsx: ', e);
    }
    console.log('end of login function')
  }

The form works, but doesn't return anything if an error happens (I can only handle it in the store -- I can't return it to the invoking function)

1 Answers

Just like you're storing your state on a successful call, you can store your error in state in your catch clause. The Zustand equivalent of dispatch doesn't return anything - it tells the reducer how to manage state.

I'm not sure how you want to put it into state, but here's an example: nesting it inside your state under the key error. Then in your component, you can check if this state exists and react accordingly. I've also cleared out the user state in the example, which you could use as well.

      .then(res => {
          set(state => {
            return {
              ...state,
              user: {
                uid: res.user.uid
              }
            }
          }, true)
        })
        .catch((error) => {
          set(state => {
            return {
              ...state,
              error,
              user: {
                uid: undefined,
              },
            }
          }, true) 
      })
Related