skip to Main Content

Since adding a catch handler to my fetch in the rare case that the server is offline or unreachable, it never returns. Execution is never broke, end point hit. I don’t get any response from my form action, no messages are displayed, and the redirect is never hit, although all scopes are reachable.

If I reload after its executed, I have my cookie and can reach /home, it just doesn’t redirect or return any validation on failure.

Here is my login action;

export const actions = {
    login: async ({ cookies, request }) => {
        const data = await request.formData();
        const objectData = Object.fromEntries(data.entries());
        const schemaCheck = schema.safeParse(objectData);

        if (!schemaCheck.success) {
            return { success: false, errorMessages: schemaCheck.error.errors.map((error) => {
                    return error.message
                })}
        }

        await fetch(PUBLIC_API_URL + '/auth/login', {
            method: "POST",
            body: JSON.stringify(objectData)
        })
        .then(async (r) => {
            const json = await r.json()

            if (Object.prototype.hasOwnProperty.call(json, 'error_message')) {
                return { success: false, errorMessages: [json['error_message']] };
            }

            cookies.set('session', json.access_token, { path: '/' });

            redirect(303, '/home');
        })
        .catch(() => {
            return { success: false, errorMessages: ['Something went wrong, try again later.']}
        })

        console.log('hello');
    }
};

If I remove the continuation and exception handler, it works fine.

2

Answers


  1. You shouldn’t mix await with .then or .catch. The reason it doesn’t terminate the login function is because the return is in another function scope.

    You could try something like this instead:

    export const actions = {
        login: async ({ cookies, request }) => {
            const data = await request.formData();
            const objectData = Object.fromEntries(data.entries());
            const schemaCheck = schema.safeParse(objectData);
    
            if (!schemaCheck.success) {
                return {
                    success: false, errorMessages: schemaCheck.error.errors.map((error) => {
                        return error.message
                    })
                }
            }
    
            try {
                const r = await fetch(PUBLIC_API_URL + '/auth/login', {
                    method: "POST",
                    body: JSON.stringify(objectData)
                });
                const json = await r.json()
                if (Object.prototype.hasOwnProperty.call(json, 'error_message')) {
                    return { success: false, errorMessages: [json['error_message']] };
                }
                cookies.set('session', json.access_token, { path: '/' });
                redirect(303, '/home');
            } catch (ex) {
                console.error('ERROR', ex);
                return { success: false, errorMessages: ['Something went wrong, try again later.'] }
            }
    
            console.log('hello');
        }
    };
    

    The catch block also catches errors caused in await fetch, so if your API didn’t work, it will also go to the catch block.

    Login or Signup to reply.
  2. The returns are inside a nested function, you would need to return await fetch(...) to get the result out of there.
    redirect works by throwing an exception, if you just catch that again, this will never work.

    You could probably restructure this by using the second then argument, which does not catch errors thrown in the success callback.

    return await fetch(...)
      .then(
        async (r) => {
          // ...
          redirect(...);
        },
        () => {
          return { success: false, errorMessages: ... }
        }
      );
    

    You could also avoid the chaining syntax, but you would have to work around redirect using an exception (e.g. catch and re-throw it).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search