Return data from SWR mutate after login

Viewed 525

I have nextJS application with Laravel backend, and I am trying to use Laravel-NextJS

All login and backend functions work fine.

Here is some login

export const useAuthLaravel = ({ middleware } = {}) => {
    
    const router = useRouter()
    
    const { data: user, error, mutate } = useSWR('/api/user', () =>
        axios
            .get('/api/user')
            .then(res => res.data)
            .catch(error => {
                if (error.response.status != 409) throw error

                router.push('/verify-email')
            }),

    )
    
    const csrf = () => axios.get('/sanctum/csrf-cookie')

    const login_laravel = async ({ setErrors, setStatus, ...props  }) => {

        await csrf()

        setErrors([])
        setStatus(null)

        axios
            .post('/login', props)
            .then(() => mutate())
            .catch(error => {
                if (error.response.status != 422) throw error
                setErrors(Object.values(error.response.data.errors).flat())
            })
    }

    useEffect(() => {
            if (middleware == 'guest' && user) return user
            if (middleware == 'auth' && error && !user) logout_laravel()
        }, [user, error])

        return {
            user,
            csrf,
            login_laravel,
        }
    }

Now above returned values of user I am trying to put in AuthContext,

import { createContext, useEffect, useReducer, useState } from 'react';
import { authApi } from 'src/mocks/auth';


const initialState = {
  isAuthenticated: false,
  isInitialized: false,
  user: null
};

export const AuthProvider = (props) => {

  const { login_laravel, logout_laravel, user } = useAuthLaravel()

  const [state, dispatch] = useReducer(reducer, initialAuthState);

  useEffect(() => {   
        
    const initialize = async () => {

      try {
        if (user) {
          console.log('user exist')
          dispatch({
            type: 'INITIALIZE',
            payload: {
              isAuthenticated: true,
              user
            }
          });
        } else {
          console.log('user not exist')
          dispatch({
            type: 'INITIALIZE',
            payload: {
              isAuthenticated: false,
              user: null
            }
          });
        }
      } catch (err) {
        console.error(err);
        dispatch({
          type: 'INITIALIZE',
          payload: {
            isAuthenticated: false,
            user: null
          }
        });
      }
    };

    initialize();

  }, []);

  const login = async (email, password) => {

    try {
      const user = await login_laravel({ email, password, setErrors, setStatus });

      dispatch({
        type: 'LOGIN',
        isAuthenticated: true,
        payload: {
          user
        }
      });
   
    } catch (err) {
      dispatch({
        type: 'LOGIN',
        payload: {
          isAuthenticated: false,
          user: null
        }
      });
    }
  };

  return (
    <AuthContext.Provider
      value={{
        ...state,
        method: 'LARAVEL',
        login,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

Now, when login function is run, it runs SWR validations, but when login finished, it does not return muted user back to AuthProvider function,

Does useAuthLaravel will run again after mutate and login function?

Thank you,

Not sure what sequence is getting wrong, any hints?

1 Answers

As I understand, you are trying to validate your user in UseEffect based on data from useSWR. These are "similar". My opinion is you need to modify return function for your page and not try to use validation in useEffect. (useEffect and useSWR triggers on page load, useEffect can be loaded faster than useSWR)

How I am doing this:

if (data){
        //trigger a function to validate your data
        return(
            <>
              <div>{something}</div>
            </>
            )
    }

if (error){
        //trigger a function to validate your data
        return (
            <div>
                
            </div>
        )
    }

I am not sure it's what you are actually looking for. But I suggest you to do all data manipulations on the backend side or in getServerSideProps and not to load huge functions at the front end side. In perfect world you need to send fully fetched data to your front end.

Related