Exposing child functions using imperativeHandle and forwardRef
This story is about a way to expose custom functions to parents in react
or react-native
.
Eunho Lee has recently contributed to @dooboo-ui/native, a beautiful react-native
element, TinderCard.
Many of you may be familiar with this UI since it has been known as an innovative UI/UX around the world. Therefore, we’ve also thought of implementing one in our UI library for react-native.
Currently, the features are pretty simple.
- You can swipe your card on the right or left.
- You can undo your swipe.
- You can swipe a card just by pressing the button.
If you have thought of building a TinderCard
, you may have a question on where to put LEFT
/UNDO
/RIGHT
buttons as shown above in the gif
image. Should they be placed inside the library element or expose render functions to parents?
Well, I thought of exposing just the functions
without doing any of the above. I just thought it would be the best scenario as being a UI library
.
So how to achieve it?
Below are the steps to do the above job.
1. Use forwardRef
inside the child element.
2. Use imperativeHandle
to expose the functions to parents.
3. Expose typescript typings for typescript users.
4. Use it in parent with useRef
.
Now go back to where you want to use TinderCard
.
Then add ReactElement
in your parent element.
<TinderCard
testID="tinderCard"
ref={tinderCard}
onSwipeRight={handleUnlike}
onSwipeLeft={handleLike}
onCancel={handleCancel}
data={data}
renderCards={_renderCards}
rotate
stackSize={0}
/><TouchableOpacity
onPress={(): void => {
tinderCard.current.forceSwipe(TinderCardDirection.LEFT);
}}
><Text>LEFT</Text></TouchableOpacity>
<TouchableOpacity
onPress={(): void => {
tinderCard.current.handleCancel();
}}
><Text>UNDO</Text></TouchableOpacity>
<TouchableOpacity
onPress={(): void => {
tinderCard.current.forceSwipe(TinderCardDirection.RIGHT);
}}
><Text>RIGHT</Text></TouchableOpacity>
That’s it!
You can see the full source code in our first PR.
The remaining issue is passing generic type
to Props
interface and removing any
for the item type. I found it pretty tricky to pass generic props to RefForwardingComponent
. I hope someone can help us out of the box.
Update: Jongtaek Choi has contributed for generic typing in #137 🎉