

Luís Freitas
|
2021-05-28
|
35 mins to read
Make it make sense! React states need not be “trapped” in a component and its children. Instead, picture this:
You have a React component with some advanced logic and context that outputs some interesting results;
Those results are part of a component’s state and you’d like to leverage them somewhere else in your application.
Let us delve into how we can make an element be truly “transformative” to those that know about it’s reference.
What we will cover
Some context;
- A primer on forwardRef;
- Introducing imperative handles;
An abstract example;
Closing thoughts.
Context
The added challenge here is the fact that it is not usually a great idea to make whatever it is you’re working on go through a major refactor when in the middle of introducing a new feature.
The shared mindset was:
more optimizing the new things we introduce and less reinventing the wheel which proved to be a useful mindset and allowed us to retrofit existing code to match the new patterns we discovered.

This new feature introduces several instances of a complex text editor to an already highly dynamic page so my code reusing patterns from the good and not-so-old C++ days came back to me and I thought:
If only there was a way to make those fancy editor components reusable and take advantage of the fact that they manage their own state internally, making only the data we’re interested in available at a given time, e.g. in event handling callbacks...
Enter React’s forwardRef
The useImperativeHandle hook
useImperativeHandle(ref, createHandle, [deps])

() => editorContext
we make the internal editor context data available to whoever knows about (or owns) the ref passed into the editor.
onBlur={() => {
if (props.onBlur) props.onBlur(ref)
}}
An abstract example
Recalling our need to avoid re-renders, let us build a simplified pattern that would allow us to access editor context from the parent component and dispatch a manipulated result to some state reducer:
import MyFancyEditor from ‘./MyFancyEditor’
import { useSomeReducer } from ‘./SomeContextProvider’const ParentComponent = () => { const { dispatch } = useSomeReducer();
const editorRef = React.createRef();return(
// Some other components
<MyFancyEditor
ref={editorRef}
onBlur={({current}) => dispatch({
// Some other values
document: current.helpers.getJSON(current.state),
})
}
/>
)}
Closing thoughts
Refs and imperative handles can have the level of complexity we’d like to provide them with, and that’s the beauty of using them!
With forwardRef and useImperativeHandle you can implicitly adopt the for React components.
Similar to anything in JavaScript, the returned context should have well-defined properties that can be modified or at least observed without completely breaking the component in the process — granted you do not forget this, move on do ref great things!
See other
Articles
