Uncontrolled component  Uncontrolled component data is handled by the DOM.   We need to use  useRef()   hook  to get form values from the DOM.  inpRef.current  refers to the DOM element. 
      import React, { useRef, useState } from 'react';
      function UncontrolledInput() {
        const [inpVal, setInpVal] = useState('initial text');
        const inpRef = useRef('initial text')
        return (
          <>
            <h1>{inpVal}</h1>
            <input
              ref={inpRef}
              type="text"
              value={inpVal}
              onChange={() => setInpVal(inpRef.current.value)}
            />
          </>
        );
      }
      <UncontrolledInput />
        Controlled component Controlled component data is handled by a React component via  useState()   hook .  Event handler takes care of a state update. 
      import React, { useRef, useState } from 'react';
      function ControlledInput() {
        const [inpVal, setInpVal] = useState('initial text');
        return (
          <>
            <h1>{inpVal}</h1>
            <input
              type="text"
              value={inpVal}
              onChange={e => setInpVal(e.target.value)}
            />
          </>
        );
      }
      <ControlledInput />
        Custom hook for input Form with input With controlled component input values are always driven by the React state and we always need to create such logic for every input. We control input value via react state with  onChange  event On form submit we prevent the default action and do our logic After submission we reset input fields with initial empty string 
      function FormWithInputWithoutCustomHook() {
        const [nameState, setNameState] = useState('')
        const submitHandler = e => {
          e.preventDefault()
          alert(`hello ${nameState}`)
          setNameState('')
        }
        return (
          <form onSubmit={submitHandler}>
            <input placeholder="Name" value={nameState} onChange={e => setNameState(e.target.value)} />
            <button>Submit</button>
          </form>
        )
      }
      <FormWithInputWithoutCustomHook />
        Custom hook for input Let's make a custom hook for an input control We extract the logic into a separate file  useInput.js  and export back the input  value  &  onChange  attributes in the object + reset function 
      // functions\ useInput.js
      import { useState } from 'react'
      export default function useInput(initVal = '') {
        const [val, setVal] = useState(initVal)
        const reset = () => setVal(initVal)
        const bind = {
          value: val,
          onChange: e => setVal(e.target.value)
        }
        return [val, bind, reset]
      }
       Input with custom hook In the main file we bring and destruct values from the custom hook Note how we bring  value  and  onChange  attributes by spreading the object into the input field 
      import useInput from '/functions/useInput'
      function FormWithInputWithCustomHook() {
        const [nameState, bindName, resetName] = useInput()
        const submitHandler = e => {
          e.preventDefault()
          alert(`hello ${nameState}`)
          resetName()
        }
        return (
          <form onSubmit={submitHandler}>
            <input placeholder="Name" {...bindName} />
            <button>Submit</button>
          </form>
        )
      }
      <FormWithInputWithCustomHook />