Formik 'initialValues' Typescript Errors in React.js with hooks

Viewed 1025

My react.js registration form works fine, then decided to apply Formik to it and got stuck on 2 issues: I keep getting a TS error message on 'initialValues' from within the 'Formik' tag. Also, after switching 'input' to 'Field' tag, parameter function 'e' from onChange also displays an underline ts error. Same issue with style property from 'ErrorMessage' tag.
I am only trying to apply a simple Formik approach to my form. Any suggestions please?

import React, { useState, FormEvent, useRef } from 'react';
import { Link, withRouter, useHistory } from 'react-router-dom';
import api from '../services/api';
import PrimaryButton from "../components/PrimaryButton";
import * as Yup from 'yup';
import { useForm } from 'react-hook-form';
import { Formik, Field, Form, ErrorMessage } from 'formik';


const userSchema = Yup.object().shape({
  name: Yup.string().required('Nome obrigatório.').max(60),
  email: Yup.string().required('Email obrigatório'),
  password: Yup.string().required('Senha obrigatória').min(4, 'Ops, curta demais.').max(10, 'Ops, longa demais.'), 
})

  function Register() {
  const history = useHistory(); 

    const [name, setName] = useState('');
    const [email, setEmail] = useState('');
    const [firstPassword, setFirstPassword] = useState('');  
    const [password, setPassword] = useState('');  
    
    const { register, handleSubmit, errors, getValues } = useForm();
    // const inputPassword = useRef(null)

      async function handleAddDev(e: FormEvent) {
          // e.preventDefault();
          let formData = {
            name,
            email,
            password,  
          }
          const isValid = await userSchema.isValid(formData);
          console.log(isValid);
          const response = await api.post('/users/new', formData)   
          console.log(response.data);
          alert('Cadastro efetuado com sucesso.')

          setName('');
          setEmail('');
          setFirstPassword('');
          setPassword('');
        
        history.push('/')
      }    

      const myValues = {
        name: "",
        email: "",
        firstPassword: "",
        password: "",
      }
      
    return (
        <>       
        <div id="register">          
           <strong>Cadastrar Usuário</strong>
           <Formik  
                initialValues={myValues}
                validationSchema={userSchema}
                onSubmit={handleAddDev}>
         
           <Form  >
            <div className="input-block">
              <label htmlFor="name">Nome</label>
              <Field 
                name="name" 
                id="name" 
                type="text"
                placeholder= "Seu nome"
                value={name}
                onChange={e => setName(e.target.value)}
                required />
              <ErrorMessage 
                name="name"
                component="div"
                className="invalid-feedback"
                style={{ color:"red", fontWeight:"bold"}}/>
            </div>
            
            <div className="input-block">
              <label htmlFor="email">E-mail</label>
              <Field
                name="email" 
                id="email" 
                type="email"
                placeholder= "Seu email"
                value={email}
                onChange={e => setEmail(e.target.value)}
                 />
                <ErrorMessage 
                  name="email"
                  component="div"
                  className="invalid-feedback"
                  style={{ color:"red", fontWeight:"bold"}}/>
            </div>

            <div className="input-block">
              <label htmlFor="email">Senha</label>
              <Field
                name="password" 
                id="password" 
                type="text"
                placeholder= "Senha"
                value={firstPassword}
                onChange={e => setFirstPassword(e.target.value)}
                ref={register}/>
               <ErrorMessage 
                  name="password"
                  component="div"
                  className="invalid-feedback"
                  style={{ color:"red", fontWeight:"bold"}}/>
            </div>

            <div className="input-block">
              <label htmlFor="email">Confirmar Senha</label>
              <Field 
                name="passwordConfirmation" 
                id="password" 
                type="text"
                placeholder= "Confirme sua sehna"
                ref={register({
                  validate: {
                    passwordEqual: value => (value === getValues().password) || 'Password confirmation error!',
                  }
                })}                
                value={password}
                onChange={e => setPassword(e.target.value)}
                required />
                <ErrorMessage 
                  name="name"
                  component="div"
                  className="invalid-feedback"
                  style={{ color:"red", fontWeight:"bold"}}/>
                {errors.passwordConfirmation && <p>{errors.passwordConfirmation.message}</p>}
            </div>                 

            <PrimaryButton type="submit">Cadastrar</PrimaryButton>  
          </Form>
          
          </Formik>
          <button><Link to='/'></Link> </button>             
       
        </div>   


        </>
    )
}

export default withRouter(Register);

2 Answers

If your file extesion is tsx, you need to define a interface for the form values:

interface MyFormValues {
      name: string,
        email: string,
        firstPassword: string,
        password: string,
}

const myValues: MyFormValues = {
        name: "",
        email: "",
        firstPassword: "",
        password: "",
      }

For the field error, the value and onChange is handled by formic so you don't need them anymore. https://formik.org/docs/guides/typescript

 const myValues = {
    name: "",
    email: "",
    firstPassword: "",
    password: "",
  }

You do not have field name 'firstPassword'. Instead you have name="passwordConfirmation". initial values must match the field names.

Regarding second issue:

   onChange = {(e: React.FormEvent<HTMLInputElement>)=>setFirstPassword(e.target.value)}
Related