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)
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.
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")
}
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}/>
)
})
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}/>
)
})