Search code examples
javascriptqwik

Qwik js TypeError: props.redirect is not a function


In one of my component, I'm passing "redirect" & trying to redirect users in specific conditions. But at the time of doing it, I'm getting the following error -

TypeError: props.redirect is not a function

at this piece of code

if (loginForm.response.status) {
    throw redirect(302, "/dashboard");
}

Component Code

import { $, component$ } from "@builder.io/qwik";
import { routeLoader$, z, RequestEvent } from "@builder.io/qwik-city";
import type { DocumentHead } from "@builder.io/qwik-city";
import { Link } from "@builder.io/qwik-city";
import type { InitialValues, SubmitHandler } from "@modular-forms/qwik";
import { formAction$, useForm, zodForm$ } from "@modular-forms/qwik";
import { account } from "~/appwrite.config";

const loginSchema = z.object({
email: z
    .string()
    .min(1, "Please enter your email.")
    .email("The email address is badly formatted."),
password: z
    .string()
    .min(1, "Please enter your password.")
    .min(8, "You password must have 8 characters or more."),
});

type LoginForm = z.infer<typeof loginSchema>;

export const useFormLoader = routeLoader$<InitialValues<LoginForm>>(() => ({
    email: "",
    password: "",
}));

type ResponseData = {
    userId: string;
};

export const useFormAction = formAction$<LoginForm>(async (values) => {
    console.log("On Server...");

    const promise = account.createEmailSession(values.email, values.password);

    const result = promise.then(
        function (response) {
        console.log("Promise Success: ", response);

        const userId = response.userId;

        return {
            status: true,
            message: "Authentication successfully done",
            data: {
            userId: userId,
            },
        };
        },
        function (error) {
        console.log("Exception Caught: ", error);
        return {
            status: false,
            data: {
            error: {
                message: error.response.message,
                code: error.code,
                type: error.type,
                version: error.response.version,
            },
            },
            message: "Exception caught when creating user account",
        };
        }
    );

    return result;
}, zodForm$(loginSchema));

export default component$(({ redirect }: RequestEvent) => {
    const [loginForm, { Form, Field }] = useForm<LoginForm>({
        loader: useFormLoader(),
        action: useFormAction(),
        validate: zodForm$(loginSchema),
    });

    console.log("loginForm Result: ", loginForm.response);

    if (loginForm.response.status) {
        throw redirect(302, "/dashboard");
    }

    type signinFormData = {
        email: string;
        password: string;
    };

    const handleSubmit: SubmitHandler<LoginForm> = $(
        (values: signinFormData, event) => {
        console.log("form data: ", values);
        }
    );

    return (
        <>
            <section class="bg-gray-50 dark:bg-gray-900">
                <div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
                <a
                    href="#"
                    class="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white"
                >
                    <img
                    class="w-8 h-8 mr-2"
                    src="https://flowbite.s3.amazonaws.com/blocks/marketing-ui/logo.svg"
                    alt="logo"
                    />
                    Lemonlist
                </a>
                <div class="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700">
                    <div class="p-6 space-y-4 md:space-y-6 sm:p-8">
                    <h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white">
                        Sign in to your account
                    </h1>
                    <Form class="space-y-4 md:space-y-6" onSubmit$={handleSubmit}>
                        <Field name="email">
                        {(field, props) => (
                            <div>
                            <label
                                for="email"
                                class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
                            >
                                Your email
                            </label>
                            <input
                                {...props}
                                type="email"
                                value={field.value}
                                class={[
                                "bg-gray-50 border  text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500",
                                field.error ? "border-red-300" : "border-gray-300",
                                ]}
                                placeholder="name@company.com"
                            />

                            {field.error && (
                                <p class="mt-2 text-sm text-red-600 dark:text-red-500">
                                {field.error}
                                </p>
                            )}
                            </div>
                        )}
                        </Field>

                        <Field name="password">
                        {(field, props) => (
                            <div>
                            <label
                                for="password"
                                class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
                            >
                                Password
                            </label>
                            <input
                                {...props}
                                type="password"
                                value={field.value}
                                placeholder="••••••••"
                                class={[
                                "bg-gray-50 border text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500",
                                field.error ? "border-red-300" : "border-gray-300",
                                ]}
                            />

                            {field.error && (
                                <p class="mt-2 text-sm text-red-600 dark:text-red-500">
                                {field.error}
                                </p>
                            )}
                            </div>
                        )}
                        </Field>

                        <div class="flex items-center justify-between">
                        <div class="flex items-start">
                        </div>
                        <a
                            href="#"
                            class="text-sm font-medium text-primary-600 hover:underline dark:text-primary-500"
                        >
                            Forgot password?
                        </a>
                        </div>

                        <button
                        type="submit"
                        class="w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"
                        >
                        Sign in
                        </button>
                        <p class="text-sm font-light text-gray-500 dark:text-gray-400">
                        Don’t have an account yet?
                        <Link
                            href="/account/signup"
                            class="ml-3 font-medium text-primary-600 hover:underline dark:text-primary-500"
                        >
                            Sign up
                        </Link>
                        </p>
                    </Form>
                    {JSON.stringify(loginForm.response)}

                    {loginForm.response.status === false &&
                        (loginForm.response.data.error.type ===
                        "general_rate_limit_exceeded" ||
                        loginForm.response.data.error.type ===
                            "user_invalid_credentials") && (
                        <>
                            <div
                            class="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400"
                            role="alert"
                            >
                            {loginForm.response.data.error.message}
                            </div>
                        </>
                        )}
                    </div>
                </div>
                </div>
            </section>
        </>
    );
});

export const head: DocumentHead = {
    title: "Dashboard",
    meta: [
        {
        name: "description",
        content: "Qwik site description",
        },
    ],
};

Maybe it's a small mistake; I'm doing it somewhere. But I can't able to understand what it is.

--- Update ---

After using "useNavigate$" in following way it's redirecing to other page but with following error.

if (loginForm.response.status) {
  nav("/dashboard");
}

enter image description here


Solution

  • You can use redirect inside routeAction$, routeLoader$, etc. etc. here is the official documentation. component$ doesn't have redirect, but you can use useNavigate$