node.jsreactjsformsform-fields

Cannot be used as a JSX component. Return type 'void' is not a valid JSX element.ts(2786)


And it returns me this: 'FormField' cannot be used as a JSX component. Its return type 'void' is not a valid JSX element.ts(2786) I don't know what I'm doing wrong.

I've created a component called 'FormField' to make the code cleaner and avoid redundancies. It's imported to the login form via the import.

login.tsx

import { Layout } from "~/components/layout";
import { FormField } from "~/components/form-field";
import { useState } from "react";

export default function Login() {
  const [formData, setFormData] = useState({
    email: "",
    password: "",
  });

  // Updates the form data when an input changes
  const handleInputChange = (
    event: React.ChangeEvent<HTMLInputElement>,
    field: string
  ) =>
    setFormData((form) => ({
      ...form,
      [field]: event.target.value,
    }));

  return (
    <Layout>
      <div className="h-full flex justify-center items-center flex-col gap-y-4">
        <form className="rounded-2xl bg-gray-200 p-6 w-96">
          <FormField
            htmlFor="email"
            label="Email"
            value={formData.email}
            onChange={(e) => handleInputChange(e, "email")}
          />
        </form>
      </div>
    </Layout>
  );
}

form-field.tsx

import { useState, useEffect } from 'react'
interface FormFieldProps {
    htmlFor: string,
    label: string,
    type?: string,
    value: any,
    onChange?: (...args: any) => any,
    error?: string
}

export function FormField({
    htmlFor,
    label,
    type = "text",
    value,
    onChange = () => { },
    error = ""

}: FormFieldProps) {
    const [errorText, setErrorText] = useState(error)

    useEffect(() => {
        setErrorText(error)
    }, [error])

    return
    <>
        <label htmlFor={htmlFor} className="text-blue-600 font-semibold">{label}</label>
        <input onChange={e => {
            onChange(e)
            setErrorText('')
        }} type={type} id={htmlFor} name={htmlFor} className="w-full p-2 rounded-xl my-2" value={value} />
        <div className="text-xs font-semibold text-center tracking-wide text-red-500 w-full">
            {errorText || ''}
        </div>
    </>
}

Solution

  • You should wrap the JSX with parentheses because the return statement currently returns nothing/void.

    export function FormField({
        htmlFor,
        label,
        type = "text",
        value,
        onChange = () => { },
        error = ""
    
    }: FormFieldProps) {
        const [errorText, setErrorText] = useState(error)
    
        useEffect(() => {
            setErrorText(error)
        }, [error])
    
        return (
          <>
            <label htmlFor={htmlFor} className="text-blue-600 font-semibold">{label}</label>
            <input onChange={e => {
                onChange(e)
                setErrorText('')
            }} type={type} id={htmlFor} name={htmlFor} className="w-full p-2 rounded-xl my-2" value={value} />
            <div className="text-xs font-semibold text-center tracking-wide text-red-500 w-full">
                {errorText || ''}
            </div>
          </>
        );
    }