From 26f54e00859e258ec39e6a23712c0cb75796e5c9 Mon Sep 17 00:00:00 2001 From: Kirill Zyusko Date: Mon, 26 Aug 2024 11:43:07 +0200 Subject: [PATCH] docs: comparison with `useAnimatedKeyboard` (#567) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📜 Description Added a note about `useAnimatedKeyboard` and this library difference. ## 💡 Motivation and Context To keep people aware on high level what is the difference between implementation. In future I may revisit the table and make some adjustments - it's only basic work. Closes https://github.com/kirillzyusko/react-native-keyboard-controller/issues/561 ## 📢 Changelog ### Docs - added a note about simultaneous usage of `useAnimatedKeyboard` and this library; - add comparison table for `useAnimatedKeyboard` and this library. ## 🤔 How Has This Been Tested? Tested manually on and via preview. ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed --- cspell.json | 4 +- docs/docs/guides/first-animation.md | 2 +- docs/docs/installation.mdx | 6 ++ docs/docs/recipes/architecture.md | 30 --------- docs/docs/recipes/architecture.mdx | 66 +++++++++++++++++++ .../version-1.13.0/guides/first-animation.md | 2 +- .../version-1.13.0/installation.mdx | 6 ++ .../version-1.13.0/recipes/architecture.md | 30 --------- .../version-1.13.0/recipes/architecture.mdx | 66 +++++++++++++++++++ 9 files changed, 149 insertions(+), 63 deletions(-) delete mode 100644 docs/docs/recipes/architecture.md create mode 100644 docs/docs/recipes/architecture.mdx delete mode 100644 docs/versioned_docs/version-1.13.0/recipes/architecture.md create mode 100644 docs/versioned_docs/version-1.13.0/recipes/architecture.mdx diff --git a/cspell.json b/cspell.json index 755faaf0df..b0fc29eca3 100644 --- a/cspell.json +++ b/cspell.json @@ -117,7 +117,9 @@ "Raphson", "desmos", "swmansion", - "rnscreens" + "rnscreens", + "setinputmode", + "useanimatedkeyboard" ], "ignorePaths": [ "node_modules", diff --git a/docs/docs/guides/first-animation.md b/docs/docs/guides/first-animation.md index e95515a47f..94f318c1ae 100644 --- a/docs/docs/guides/first-animation.md +++ b/docs/docs/guides/first-animation.md @@ -85,5 +85,5 @@ export default function KeyboardAnimation() { ``` :::info -If you are going to use these Animated values in class components (i.e. without hooks) - you can easily [do](../api/hooks/keyboard/use-keyboard-animation.md) it. Check out [source](https://github.com/kirillzyusko/react-native-keyboard-controller/blob/cf27eb00877db34b860a04cf52a026110e44b4b3/src/animated.tsx#L46-L51) code - this hook simply changes `softInputMode` and consumes `Context`. Also you may read [architecture](../recipes/architecture.md) deep dive to understand more about how this library works. +If you are going to use these Animated values in class components (i.e. without hooks) - you can easily [do](../api/hooks/keyboard/use-keyboard-animation.md) it. Check out [source](https://github.com/kirillzyusko/react-native-keyboard-controller/blob/cf27eb00877db34b860a04cf52a026110e44b4b3/src/animated.tsx#L46-L51) code - this hook simply changes `softInputMode` and consumes `Context`. Also you may read [architecture](../recipes/architecture.mdx) deep dive to understand more about how this library works. ::: diff --git a/docs/docs/installation.mdx b/docs/docs/installation.mdx index ca12c8d0c1..671965a4a1 100644 --- a/docs/docs/installation.mdx +++ b/docs/docs/installation.mdx @@ -45,6 +45,12 @@ npm install react-native-keyboard-controller --save This library requires `react-native-reanimated` to work properly. If you don't have it in your project, you need to follow [installation guide](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#installation) and install it in your project before using this library. ::: +:::info Usage with `useAnimatedKeyboard` hook from `react-native-reanimated` +`react-native-keyboard-controller` and `useAnimatedKeyboard` hook (from `react-native-reanimated`) _**may**_ technically be used together, but it's **highly recommended** to use only one of them to avoid any kind of conflicts. + +If you want to know the difference between `useAnimatedKeyboard` and the implementation of this library, please read [this comparison](./recipes/architecture#what-is-the-difference-between-useanimatedkeyboard-from-react-native-reanimated-and-this-library). +::: + ### Linking This package supports [autolinking](https://github.com/react-native-community/cli/blob/master/docs/autolinking.md). diff --git a/docs/docs/recipes/architecture.md b/docs/docs/recipes/architecture.md deleted file mode 100644 index 1cdcddde93..0000000000 --- a/docs/docs/recipes/architecture.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -sidebar_position: 1 -keywords: [react-native-keyboard-controller, architecture, design principles] ---- - -# Architecture - -This library requires to wrap an app with `KeyboardProvider` component. It's needed because it stores animated values in `context`. - -## Process overview - -Library exposes `KeyboardControllerView` with `onKeyboardMove` method. This method is fired when keyboard frame is changed. `KeyboardProvider` automatically maps these events to `Animated.Value` and `Reanimated.SharedValue` and stores it in `context`. - -:::info -Under the hood `KeyboardControllerView` is a simple `View` with one additional `onKeyboardMove` callback method, so it inherits all props from plain `View`, such as `style`, etc. -::: - -Thus we have a single source of truth about keyboard position. Since values are stored in `context` we can use it in any component where we need them. Moreover, we can consume `context` values in class components as well as in hooks. - -## Design principles - -The library was designed to use a `context` as a global store for animated values and have a single `Provider` across the app. As of now it may be not very obvious, why it was needed to have a single source of data flow, but in future it may significantly simplify the process of the integration new features. - -## Why custom `KeyboardControllerView` is needed? - -Initially I had a choice which approach to use in order to send events about keyboard frames: `EventEmitters` vs `View` with callbacks. I decided to use `View` with callbacks because of several reasons: - -- `react-native` core team uses similar approach for `onScroll` event from `ScrollView` component (also I knew, that it's possible to map events from such callbacks to `Animated.Value` and thus reduce bridge usage); -- to track keyboard frames on Android we need to enter to [edge-to-edge](https://developer.android.com/training/gestures/edge-to-edge) mode and it changes view paddings. Since it's managed through `View` it's easier to change padding of this view. -- `reanimated` allows to intercept `view` events using theirs `useEvent` hook and move the event handling into worklet runtime. Thus sending events via `view` allows to make an integration with `reanimated` package and handle events/animate everything directly on the UI thread. diff --git a/docs/docs/recipes/architecture.mdx b/docs/docs/recipes/architecture.mdx new file mode 100644 index 0000000000..30378fe84b --- /dev/null +++ b/docs/docs/recipes/architecture.mdx @@ -0,0 +1,66 @@ +--- +sidebar_position: 1 +keywords: [react-native-keyboard-controller, architecture, design principles] +--- + +# Architecture + +This library requires to wrap an app with `KeyboardProvider` component. It's needed because it stores animated values in `context`. + +## Process overview + +Library exposes `KeyboardControllerView` with `onKeyboardMove` method. This method is fired when keyboard frame is changed. `KeyboardProvider` automatically maps these events to `Animated.Value` and `Reanimated.SharedValue` and stores it in `context`. + +:::info +Under the hood `KeyboardControllerView` is a simple `View` with one additional `onKeyboardMove` callback method, so it inherits all props from plain `View`, such as `style`, etc. +::: + +Thus we have a single source of truth about keyboard position. Since values are stored in `context` we can use it in any component where we need them. Moreover, we can consume `context` values in class components as well as in hooks. + +## Design principles + +The library was designed to use a `context` as a global store for animated values and have a single `Provider` across the app. As of now it may be not very obvious, why it was needed to have a single source of data flow, but in future it may significantly simplify the process of the integration new features. + +## Why custom `KeyboardControllerView` is needed? + +Initially I had a choice which approach to use in order to send events about keyboard frames: `EventEmitters` vs `View` with callbacks. I decided to use `View` with callbacks because of several reasons: + +- `react-native` core team uses similar approach for `onScroll` event from `ScrollView` component (also I knew, that it's possible to map events from such callbacks to `Animated.Value` and thus reduce bridge usage); +- to track keyboard frames on Android we need to enter to [edge-to-edge](https://developer.android.com/training/gestures/edge-to-edge) mode and it changes view paddings. Since it's managed through `View` it's easier to change padding of this view. +- `reanimated` allows to intercept `view` events using theirs `useEvent` hook and move the event handling into worklet runtime. Thus sending events via `view` allows to make an integration with `reanimated` package and handle events/animate everything directly on the UI thread. + +## What is the difference between `useAnimatedKeyboard` from `react-native-reanimated` and this library? + +`react-native-keyboard-controller` uses its own implementation for keyboard handling and leverages `react-native-reanimated` solely for performing UI thread updates using `SharedValue` (the library doesn't simply re-export `useAnimatedKeyboard` hook in any kind of form). + +While both `useAnimatedKeyboard` from `react-native-reanimated` and this library aims to provide the same functionality, there are some differences between them. Below you can find a comparison of the two libraries: + + +| |`react-native-keyboard-controller`|`react-native-reanimated`| +|-|----------------------------------|-------------------------| +|Map keyboard movement to animated value|✅|✅| +|Synchronously update keyboard position on UI thread|✅|✅| +|Dynamically switch [`softInputMode`](../api//keyboard-controller.md#setinputmode-)|✅|❌| +|An ability to turn functionality on demand|✅|🟠 1| +|Android interactive keyboard support|✅|❌| +|iOS interactive keyboard support|✅|✅| +|Has pre-built components|✅|❌| +|Works in `Modal` on Android|✅|🟠 2|| +|Is ready-to-use library for keyboard avoidance3|✅|❌| +|`KeyboardToolbar` component|✅|❌| + + +> 1 You need to unmount all components that use `useAnimatedKeyboard` +> to disable module functionality, which can be hard to achieve if you are using +> deep Stack-navigators. + +> 2 Planned to be added in the future + +> 3 The `react-native-keyboard-controller` tracks focused input changes +> (apart of keyboard tracking) and thus brings advanced concepts for keyboard avoidance. + +To sum it up: + +- if you are using `useAnimatedKeyboard` and you are satisfied with it, then there is no sense to switch to `react-native-keyboard-controller`; + +- if you are planning to add advanced keyboard handling into large existing project, then `react-native-keyboard-controller` can be a better choice, since it has drop-in replacement components (`KeyboardAvoidingView`, `KeyboardAwareScrollView`, etc.), you can toggle the functionality dynamically on per screen basic, you can dynamically change `softInputMode` which should simplify the integration process. diff --git a/docs/versioned_docs/version-1.13.0/guides/first-animation.md b/docs/versioned_docs/version-1.13.0/guides/first-animation.md index e95515a47f..94f318c1ae 100644 --- a/docs/versioned_docs/version-1.13.0/guides/first-animation.md +++ b/docs/versioned_docs/version-1.13.0/guides/first-animation.md @@ -85,5 +85,5 @@ export default function KeyboardAnimation() { ``` :::info -If you are going to use these Animated values in class components (i.e. without hooks) - you can easily [do](../api/hooks/keyboard/use-keyboard-animation.md) it. Check out [source](https://github.com/kirillzyusko/react-native-keyboard-controller/blob/cf27eb00877db34b860a04cf52a026110e44b4b3/src/animated.tsx#L46-L51) code - this hook simply changes `softInputMode` and consumes `Context`. Also you may read [architecture](../recipes/architecture.md) deep dive to understand more about how this library works. +If you are going to use these Animated values in class components (i.e. without hooks) - you can easily [do](../api/hooks/keyboard/use-keyboard-animation.md) it. Check out [source](https://github.com/kirillzyusko/react-native-keyboard-controller/blob/cf27eb00877db34b860a04cf52a026110e44b4b3/src/animated.tsx#L46-L51) code - this hook simply changes `softInputMode` and consumes `Context`. Also you may read [architecture](../recipes/architecture.mdx) deep dive to understand more about how this library works. ::: diff --git a/docs/versioned_docs/version-1.13.0/installation.mdx b/docs/versioned_docs/version-1.13.0/installation.mdx index ca12c8d0c1..671965a4a1 100644 --- a/docs/versioned_docs/version-1.13.0/installation.mdx +++ b/docs/versioned_docs/version-1.13.0/installation.mdx @@ -45,6 +45,12 @@ npm install react-native-keyboard-controller --save This library requires `react-native-reanimated` to work properly. If you don't have it in your project, you need to follow [installation guide](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#installation) and install it in your project before using this library. ::: +:::info Usage with `useAnimatedKeyboard` hook from `react-native-reanimated` +`react-native-keyboard-controller` and `useAnimatedKeyboard` hook (from `react-native-reanimated`) _**may**_ technically be used together, but it's **highly recommended** to use only one of them to avoid any kind of conflicts. + +If you want to know the difference between `useAnimatedKeyboard` and the implementation of this library, please read [this comparison](./recipes/architecture#what-is-the-difference-between-useanimatedkeyboard-from-react-native-reanimated-and-this-library). +::: + ### Linking This package supports [autolinking](https://github.com/react-native-community/cli/blob/master/docs/autolinking.md). diff --git a/docs/versioned_docs/version-1.13.0/recipes/architecture.md b/docs/versioned_docs/version-1.13.0/recipes/architecture.md deleted file mode 100644 index 1cdcddde93..0000000000 --- a/docs/versioned_docs/version-1.13.0/recipes/architecture.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -sidebar_position: 1 -keywords: [react-native-keyboard-controller, architecture, design principles] ---- - -# Architecture - -This library requires to wrap an app with `KeyboardProvider` component. It's needed because it stores animated values in `context`. - -## Process overview - -Library exposes `KeyboardControllerView` with `onKeyboardMove` method. This method is fired when keyboard frame is changed. `KeyboardProvider` automatically maps these events to `Animated.Value` and `Reanimated.SharedValue` and stores it in `context`. - -:::info -Under the hood `KeyboardControllerView` is a simple `View` with one additional `onKeyboardMove` callback method, so it inherits all props from plain `View`, such as `style`, etc. -::: - -Thus we have a single source of truth about keyboard position. Since values are stored in `context` we can use it in any component where we need them. Moreover, we can consume `context` values in class components as well as in hooks. - -## Design principles - -The library was designed to use a `context` as a global store for animated values and have a single `Provider` across the app. As of now it may be not very obvious, why it was needed to have a single source of data flow, but in future it may significantly simplify the process of the integration new features. - -## Why custom `KeyboardControllerView` is needed? - -Initially I had a choice which approach to use in order to send events about keyboard frames: `EventEmitters` vs `View` with callbacks. I decided to use `View` with callbacks because of several reasons: - -- `react-native` core team uses similar approach for `onScroll` event from `ScrollView` component (also I knew, that it's possible to map events from such callbacks to `Animated.Value` and thus reduce bridge usage); -- to track keyboard frames on Android we need to enter to [edge-to-edge](https://developer.android.com/training/gestures/edge-to-edge) mode and it changes view paddings. Since it's managed through `View` it's easier to change padding of this view. -- `reanimated` allows to intercept `view` events using theirs `useEvent` hook and move the event handling into worklet runtime. Thus sending events via `view` allows to make an integration with `reanimated` package and handle events/animate everything directly on the UI thread. diff --git a/docs/versioned_docs/version-1.13.0/recipes/architecture.mdx b/docs/versioned_docs/version-1.13.0/recipes/architecture.mdx new file mode 100644 index 0000000000..30378fe84b --- /dev/null +++ b/docs/versioned_docs/version-1.13.0/recipes/architecture.mdx @@ -0,0 +1,66 @@ +--- +sidebar_position: 1 +keywords: [react-native-keyboard-controller, architecture, design principles] +--- + +# Architecture + +This library requires to wrap an app with `KeyboardProvider` component. It's needed because it stores animated values in `context`. + +## Process overview + +Library exposes `KeyboardControllerView` with `onKeyboardMove` method. This method is fired when keyboard frame is changed. `KeyboardProvider` automatically maps these events to `Animated.Value` and `Reanimated.SharedValue` and stores it in `context`. + +:::info +Under the hood `KeyboardControllerView` is a simple `View` with one additional `onKeyboardMove` callback method, so it inherits all props from plain `View`, such as `style`, etc. +::: + +Thus we have a single source of truth about keyboard position. Since values are stored in `context` we can use it in any component where we need them. Moreover, we can consume `context` values in class components as well as in hooks. + +## Design principles + +The library was designed to use a `context` as a global store for animated values and have a single `Provider` across the app. As of now it may be not very obvious, why it was needed to have a single source of data flow, but in future it may significantly simplify the process of the integration new features. + +## Why custom `KeyboardControllerView` is needed? + +Initially I had a choice which approach to use in order to send events about keyboard frames: `EventEmitters` vs `View` with callbacks. I decided to use `View` with callbacks because of several reasons: + +- `react-native` core team uses similar approach for `onScroll` event from `ScrollView` component (also I knew, that it's possible to map events from such callbacks to `Animated.Value` and thus reduce bridge usage); +- to track keyboard frames on Android we need to enter to [edge-to-edge](https://developer.android.com/training/gestures/edge-to-edge) mode and it changes view paddings. Since it's managed through `View` it's easier to change padding of this view. +- `reanimated` allows to intercept `view` events using theirs `useEvent` hook and move the event handling into worklet runtime. Thus sending events via `view` allows to make an integration with `reanimated` package and handle events/animate everything directly on the UI thread. + +## What is the difference between `useAnimatedKeyboard` from `react-native-reanimated` and this library? + +`react-native-keyboard-controller` uses its own implementation for keyboard handling and leverages `react-native-reanimated` solely for performing UI thread updates using `SharedValue` (the library doesn't simply re-export `useAnimatedKeyboard` hook in any kind of form). + +While both `useAnimatedKeyboard` from `react-native-reanimated` and this library aims to provide the same functionality, there are some differences between them. Below you can find a comparison of the two libraries: + + +| |`react-native-keyboard-controller`|`react-native-reanimated`| +|-|----------------------------------|-------------------------| +|Map keyboard movement to animated value|✅|✅| +|Synchronously update keyboard position on UI thread|✅|✅| +|Dynamically switch [`softInputMode`](../api//keyboard-controller.md#setinputmode-)|✅|❌| +|An ability to turn functionality on demand|✅|🟠 1| +|Android interactive keyboard support|✅|❌| +|iOS interactive keyboard support|✅|✅| +|Has pre-built components|✅|❌| +|Works in `Modal` on Android|✅|🟠 2|| +|Is ready-to-use library for keyboard avoidance3|✅|❌| +|`KeyboardToolbar` component|✅|❌| + + +> 1 You need to unmount all components that use `useAnimatedKeyboard` +> to disable module functionality, which can be hard to achieve if you are using +> deep Stack-navigators. + +> 2 Planned to be added in the future + +> 3 The `react-native-keyboard-controller` tracks focused input changes +> (apart of keyboard tracking) and thus brings advanced concepts for keyboard avoidance. + +To sum it up: + +- if you are using `useAnimatedKeyboard` and you are satisfied with it, then there is no sense to switch to `react-native-keyboard-controller`; + +- if you are planning to add advanced keyboard handling into large existing project, then `react-native-keyboard-controller` can be a better choice, since it has drop-in replacement components (`KeyboardAvoidingView`, `KeyboardAwareScrollView`, etc.), you can toggle the functionality dynamically on per screen basic, you can dynamically change `softInputMode` which should simplify the integration process.