Search code examples
reactjstypescriptsemantic-uireact-hook-form

How to solve TypeScript errors validating React Sematic UI Form with React-Hook-Form?


I am a using Semantic UI for registration Form. After creating the Form successfully I want to add validation to the Form using React-Hook-Form. The errors I encountered, are highlighted in newUser in dispatch method and related to TypeScript. I tried to add types following the documentation in React-Hook-Form website, but couldn't solve it.
Any help will be appreciated.
Here are the errors I have


No overload matches this call.
  Overload 1 of 3, '(rules?: Partial<{ required: string | boolean | ValidationValueMessage<boolean>; min: ValidationRule<ReactText>; max: ValidationRule<ReactText>; maxLength: ValidationRule<...>; minLength: ValidationRule<...>; pattern: ValidationRule<...>; validate: Validate | Record<...>; }> | undefined): (ref: HTMLInputElement | ... 15 more ... | null) => void', gave the following error.
    Type '{ firstName: string; lastName: string; email: string; password: string; }' has no properties in common with type 'Partial<{ required: string | boolean | ValidationValueMessage<boolean>; min: ValidationRule<ReactText>; max: ValidationRule<ReactText>; maxLength: ValidationRule<...>; minLength: ValidationRule<...>; pattern: ValidationRule<...>; validate: Validate | Record<...>; }>'.
      Type '{ firstName: string; lastName: string; email: string; password: string; }' is not assignable to type 'CustomElement<Inputs> & CustomElement<Record<string, any>>'.
        Property 'name' is missing in type '{ firstName: string; lastName: string; email: string; password: string; }' but required in type 'CustomElement<Inputs>'.  TS2769

    54 |                }
    55 | 
  > 56 |                dispatch(register(newUser))

And Register component


import React, { useState } from 'react'
import { useDispatch } from 'react-redux'
import { useHistory, Link } from 'react-router-dom'
import { useForm } from 'react-hook-form'
import {
    Form,
    Segment,
    Grid,
    Button,
    Card,
    Icon,
    Header,
} from 'semantic-ui-react'

import { register } from '../../../redux/User/UserActions'

type Inputs = {
    firstName: string
    lastName: string
    password: string
    email: string
}

const Register = () => {
    const { register, handleSubmit } = useForm<Inputs>()
    const dispatch = useDispatch()
    const history = useHistory()

    const [user, setUser] = useState({
        firstName: '',
        lastName: '',
        email: '',
        password: '',
    })

    const { firstName, lastName, email, password } = user

    const onChange: React.ReactEventHandler<HTMLInputElement> = (e: any) => {
        let { name, value } = e.currentTarget
        setUser({
            ...user,
            [name]: value,
        })
    }

    const handleFormSubmit = (e: any) => {
        e.preventDefault()

        const newUser = {
            firstName: firstName,
            lastName: lastName,
            email: email,
            password: password,
        }

        dispatch(register(newUser))
    }

    function handleClick() {
        if (!history) {
            return <div>No country</div>
        } else {
            history.push('/home')
        }
    }

    const registerFormValid =
        !firstName?.length ||
        !lastName?.length ||
        !password?.length ||
        !email?.length

    return (
        <>
            <Card.Group itemsPerRow={4} centered style={{ margin: 0 }}>
                <Button color="teal" onClick={handleClick}>
                    <Icon name="home"> </Icon>
                    Home
                </Button>
            </Card.Group>
            <Grid centered>
                <Grid.Column style={{ maxWidth: 550, marginTop: 20 }}>
                    <Header as="h2" color="teal" textAlign="center">
                        Create an Account
                    </Header>
                    <Segment>
                        <Form>
                            <Form.Field>
                                <Form.Input
                                    value={firstName}
                                    onChange={onChange}
                                    name="firstName"
                                    placeholder="First Name"
                                    label="First Name"
                                    ref={register}
                                />
                            </Form.Field>
                            <Form.Field>
                                <Form.Input
                                    value={lastName}
                                    onChange={onChange}
                                    name="lastName"
                                    placeholder="Last Name"
                                    label="Last Name"
                                    ref={register}
                                />
                            </Form.Field>
                            <Form.Field>
                                <Form.Input
                                    type="email"
                                    value={email}
                                    onChange={onChange}
                                    name="email"
                                    placeholder="Email"
                                    label="Email"
                                    ref={register}
                                />
                            </Form.Field>
                            <Form.Field>
                                <Form.Input
                                    value={password}
                                    onChange={onChange}
                                    type="password"
                                    name="password"
                                    placeholder="Password"
                                    label="Password"
                                    ref={register({ required: true })}
                                />
                            </Form.Field>

                            <Button
                                onSubmit={handleSubmit(handleFormSubmit)}
                                fluid
                                color="teal"
                                type="submit"
                                disabled={registerFormValid}
                            >
                                Submit
                            </Button>
                        </Form>

                        <Segment>
                            Already have an account?
                            <Link to="/login">Login</Link>.
                        </Segment>
                    </Segment>
                </Grid.Column>
            </Grid>
        </>
    )
}

export default Register

Solution

  • Just noticed, you are using 2 variables with the same name register.

     import { register } from '../../../redux/User/UserActions'
     const { register, handleSubmit } = useForm<Inputs>()
    

    I guess your intended register is the redux action, but your handleFormSubmit takes the closer one (the react-hook-form's register), which causes the TS error.

    Try rename them with clearer meaning.