Skip to content

Commit

Permalink
fix: mount handlers when view is not mounted yet (#575)
Browse files Browse the repository at this point in the history
## 📜 Description

Defer attaching workelt handlers if ref is not initialized yet.

## 💡 Motivation and Context

When we use `KeyboardAwareScrollView` next to `KeyboardProvider` we end
up in situation when ref is not initialized yet and in this case we can
not attach our handler.

This is a common scenario because documentation page tells is's a valid
code but developers can be confused by that fact that sample code is not
working and may not want to integrate the library in the code.

To fix this problem I'm deferring attaching till `ref` is initialized
(`setImmediate` does the job).

Also I added meaningful warning that will spot potential problems in
future:

<p align="center">
<img width="300"
src="https://github.com/user-attachments/assets/0686fc7b-2194-4220-8289-c202416f9912">
</p>

With all these changes I think a new code gets a better revision and
handles more edge-cases.

Closes
#574

## 📢 Changelog

<!-- High level overview of important changes -->
<!-- For example: fixed status bar manipulation; added new types
declarations; -->
<!-- If your changes don't affect one of platform/language below - then
remove this platform/language -->

### JS

- check `viewRef` for nullability and defer initialization if it's
`null`;
- check if `viewTag` is null and if it's null then print a warning.

## 🤔 How Has This Been Tested?

Tested on iPhone 15 Pro.

## 📸 Screenshots (if appropriate):

|Before|After|
|-------|-----|
|<video
src="https://github.com/user-attachments/assets/f116dafb-2f67-41d7-9d57-8d3a70fd497a">|<video
src="https://github.com/user-attachments/assets/d70994cb-18bf-439e-bd01-8319e209fcdd">|


## 📝 Checklist

- [x] CI successfully passed
- [x] I added new mocks and corresponding unit-tests if library API was
changed
  • Loading branch information
kirillzyusko authored Sep 2, 2024
1 parent e852dd9 commit 961e8a1
Showing 1 changed file with 34 additions and 15 deletions.
49 changes: 34 additions & 15 deletions src/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,44 @@ export function useEventHandlerRegistration<
viewTagRef: React.MutableRefObject<ComponentOrHandle>,
) {
const onRegisterHandler = (handler: H) => {
const viewTag = findNodeHandle(viewTagRef.current);
const ids = Object.keys(handler).map((handlerName) => {
const eventName = map.get(handlerName as keyof H);
const functionToCall = handler[handlerName as keyof H];
const ids: (number | null)[] = [];
const attachWorkletHandlers = () => {
const viewTag = findNodeHandle(viewTagRef.current);

if (eventName && viewTag) {
return registerEventHandler(
(event: Parameters<NonNullable<H[keyof H]>>[0]) => {
"worklet";

functionToCall?.(event);
},
eventName,
viewTag,
if (__DEV__ && !viewTag) {
console.warn(
"Can not attach worklet handlers for `react-native-keyboard-controller` because view tag can not be resolved. Be sure that `KeyboardProvider` is fully mounted before registering handlers. If you think it is a bug in library, please open an issue.",
);
}

return null;
});
ids.push(
...Object.keys(handler).map((handlerName) => {
const eventName = map.get(handlerName as keyof H);
const functionToCall = handler[handlerName as keyof H];

if (eventName && viewTag) {
return registerEventHandler(
(event: Parameters<NonNullable<H[keyof H]>>[0]) => {
"worklet";

functionToCall?.(event);
},
eventName,
viewTag,
);
}

return null;
}),
);
};

if (viewTagRef.current) {
attachWorkletHandlers();
} else {
// view may not be mounted yet - defer registration to next event loop
setImmediate(attachWorkletHandlers);
}

return () => {
ids.forEach((id) => (id ? unregisterEventHandler(id) : null));
Expand Down

0 comments on commit 961e8a1

Please sign in to comment.