1. Overview
useImparetiveHandler combined with forwardRef allows us to take control over child components' input elements. This tutorial explains how to use forwardRef and useImparetiveHandler to expose components dom elements to parent components or HOC (higher-order components)
2. forwardRef vs useImperativeHandle
forwardRef allows you to pass ref objects from parent components to child components, allowing you to access child components dom element. useImperativeHandle allows you to modify the ref object passed to the useImperativeHandle hook.
- useImperativeHandle allows you to customized and override the default dom elements return value.
- It allows you to override or customize default dom element events with your own.
3. useImperativeHandle example with Typescript
import { forwardRef, useImperativeHandle, useRef } from "react"
interface InputProps{
}
type RefHandler = {
}
export const RefForm = () => {
const nameRef = useRef() as React.MutableRefObject<HTMLInputElement>;
const focusHandler = () => {
nameRef.current.focus()
}
const blurHandler = () => {
nameRef.current.blur()
}
const toggleHandler = () => {
nameRef.current.toggleAttribute("Some Value")
}
const clearHandler = () => {
nameRef.current.remove()
}
return(
<>
<Input ref={nameRef}/>
<div>
<button onClick={focusHandler}>Focus</button>
<button onClick={blurHandler}>Blur</button>
<button onClick={toggleHandler}>Toggle</button>
<button onClick={clearHandler}>Clear</button>
</div>
</>
)
}
const Input = forwardRef<RefHandler,InputProps>((props, ref) => {
const nameRef = useRef() as React.MutableRefObject<HTMLInputElement>;
useImperativeHandle(ref, () => ({
focus: () => {
nameRef?.current?.focus();
},
blur: () => {
alert("Some blur function")
},
toggleAttribute: (val: string) => {
nameRef.current.value = val
},
remove: () => {
nameRef.current.value = ""
}
}));
return(
<input type="text" name="name" value="" ref={nameRef}/>
)
})
4. useImperativeHandle example with Javascript
import { forwardRef, useImperativeHandle, useRef } from "react"
export const RefForm = () => {
const nameRef = useRef()
const focusHandler = () => {
nameRef.current.focus()
}
const blurHandler = () => {
nameRef.current.blur()
}
const toggleHandler = () => {
nameRef.current.toggleAttribute("Some Value")
}
const clearHandler = () => {
nameRef.current.remove()
}
const valueHandler = () => {
alert(nameRef.current.value())
}
return(
<>
<Input ref={nameRef}/>
<div>
<button onClick={focusHandler}>Focus</button>
<button onClick={blurHandler}>Blur</button>
<button onClick={toggleHandler}>Toggle</button>
<button onClick={clearHandler}>Clear</button>
<button onClick={valueHandler}>Value</button>
</div>
</>
)
}
const Input = forwardRef((props, ref) => {
const nameRef = useRef()
useImperativeHandle(ref, () => ({
focus: () => {
nameRef?.current?.focus();
},
blur: () => {
alert("Some blur function")
},
toggleAttribute: (val) => {
nameRef.current.value = val
},
remove: () => {
nameRef.current.value = ""
},
value: () => {
return nameRef.current.value + " modified"
}
}));
return(
<input type="text" name="name" value="" ref={nameRef}/>
)
})