React

Last Updated: 4/13/2023

Building Forms

Accessing Input Fields

  • You can use useRef to get the values of input field in the form
  • useRef is a buit-in hook which you can use to reference any DOM element
  • Common practice is to initialize to null
  • Returns ref object
  • Create ref object and assign to control
const nameRef = useRef(null);
<input ref={nameRef} />
  • Get the value of control
console.log(nameRef.current.value)
  • current prop returns referenced DOM element
if(nameRef.current.value !== null)
console.log(nameRef.current.value);
  • Specify type
useRef<HTMLInputElement>();

current

  • current property references DOM node. The initial value used to set current property
  • Initially ref has no access to DOM node. DOM gets created after react renders. The current prop is set to DOM after component is rendered and set to null when node is removed from screen
  • current prop points to either DOM or null
  • If no value is passed to useRef, the current prop will be undefined and willl cause issues
  • Always initialize with null

Controlled Components

  • In HTML, form elements such as <input>, <textarea>, and <select> typically maintain their own state and update it based on user input
  • In React, mutable state is typically kept in the state property of components, and only updated with setState().
  • We can combine the two by making the React state be the single source of truth.
  • Then the React component that renders a form also controls what happens in that form on subsequent user input.
  • An input form element whose value is controlled by React in this way is called a controlled component.
const [person, setPerson] = useState({name: "",
age: ""})
<form>
<input onChange={(event) => setPerson({...person, name: event.target.value})} value={person.name} />
<input onChange={(event) => setPerson({...person, age: parseInt(event.target.value)})} value={person.age} />
</form>

React Hook Form

  • Install
npm i react-hook-form@7.43
  • Import
import {useForm} from "react-hook-form";
  • Call useForm
const {register, handleSubmit} = useForm();
  • Register Control
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("name")} />
</form>
  • Submit handler
onSubmit = (data:FieldValuess) => console.log(data);

Applying Validations

  • Create interface
interface FormData {
name: string;
age: string;
}
  • Deconstruct errors
const {register, handleSubmit, formState: {errors}} = useForm<FormData>();
  • Specify validation
<input {...register("name", {required: true, minLength: 3})} />
{errors.name?.type === "required" && <p>The name field is required</p> }
{errors.name?.type === "minLength" && <p>The name must be atleat 3 characters</p> }

Schema Based Validation

  • Popular libraries
    • Joi
    • Yup
    • Zod
  • Install zod
npm i zod@3.20.6
  • Import
import {z} from "zod";
  • Define schema
const schema = z.object({
	name: z.string().min(3, {message: "Name must be at least 3 chars"}),
	age: z.number({invalid_type_error: "Age is required"}).min(18, {message: "Age must be at least 18"})
})
  • Define interface
type FormData = z.infer<typeof schema>;
  • Install resolver
npm i @hookform/resolvers@2.9.11
  • Import resolver
import {zodResolver} from "@hookform/resolvers/zod";
  • Pass schema to react hook form using zod resolver
useForm<FormData>({resolver: zodResolver(schema)});
  • Register control
register("age", {valueAsNumber: true})	
  • Error handling
{errors.name && <p>{errors.name.message}</p> }

Disabling Button

  • Deconstruct isValid
const {register, handleSubmit, formState: {errors, isValid}} = useForm();
  • Add disblaed attribute based on isValid
<button disabled={!isValid}></button>