██╗   ██╗██╗      █████╗ ██████╗ ██╗███╗   ███╗██╗██████╗     ██╗   ██╗ ██████╗ ██╗   ██╗██╗  ██╗
  ██║   ██║██║     ██╔══██╗██╔══██╗██║████╗ ████║██║██╔══██╗    ██║   ██║██╔═══██╗██║   ██║██║ ██╔╝
  ██║   ██║██║     ███████║██║  ██║██║██╔████╔██║██║██████╔╝    ██║   ██║██║   ██║██║   ██║█████╔╝
  ╚██╗ ██╔╝██║     ██╔══██║██║  ██║██║██║╚██╔╝██║██║██╔══██╗    ╚██╗ ██╔╝██║   ██║╚██╗ ██╔╝██╔═██╗
██╗╚████╔╝ ███████╗██║  ██║██████╔╝██║██║ ╚═╝ ██║██║██║  ██║     ╚████╔╝ ╚██████╔╝ ╚████╔╝ ██║  ██╗
╚═╝ ╚═══╝  ╚══════╝╚═╝  ╚═╝╚═════╝ ╚═╝╚═╝     ╚═╝╚═╝╚═╝  ╚═╝      ╚═══╝   ╚═════╝   ╚═══╝  ╚═╝  ╚═╝

Electronic Components

Exposing Methods from React Functional Components

In React, we are using props to control our components. But sometimes we need more...

Let us imagine we are building a custom form input component. And then we need to focus on it when something happens in our app. How should we do this?

We can easily get a reference to the component with the ref prop.

...
const ref = useRef()

...
<FormInput ref={ref} />
...
...
const ref = useRef()

...
<FormInput ref={ref} />
...

But how can we expose a method from a functional component? 🤔

We can use the useImperativeHandle hook!

...

export const FormInput = ({ label, placeholder, ref }: Props) => {
const inputRef = useRef<TextInput>(null)

const focus = () => {
inputRef.current?.focus()
}

useImperativeHandle(ref, () => {
return {
focus
}
}, [])

return (
<View>
<Text style={styles.label}>{label}</Text>
<TextInput ref={inputRef} style={styles.input} placeholder={placeholder} placeholderTextColor="gray" />
</View>
)
}

...
...

export const FormInput = ({ label, placeholder, ref }: Props) => {
const inputRef = useRef<TextInput>(null)

const focus = () => {
inputRef.current?.focus()
}

useImperativeHandle(ref, () => {
return {
focus
}
}, [])

return (
<View>
<Text style={styles.label}>{label}</Text>
<TextInput ref={inputRef} style={styles.input} placeholder={placeholder} placeholderTextColor="gray" />
</View>
)
}

...

Here we have created the focus function and then exposed it with the useImperativeHandle hook. Now we can use this function in our parent component.

...

const formInputRef = useRef()

...
// use the ref to focus the component
formInputRef.current.focus()
...

return <FormInput ref={formInputRef} />

...
...

const formInputRef = useRef()

...
// use the ref to focus the component
formInputRef.current.focus()
...

return <FormInput ref={formInputRef} />

...

Yay! 🎉

❗However, do not overuse references. We should only use refs for imperative behaviors that we can not express as props (scrolling to a node, focusing a node, triggering an animation, selecting text, etc.). If we can express something as a prop, we should not use a ref.

Please see the full example and play with the code using this Expo Snack. 👀

Credits

Photo by Robin Glauser on Unsplash.