mirror of
https://github.com/bigskysoftware/hypermedia-systems.git
synced 2025-12-04 00:05:18 -05:00
edits, hypermedia-driven, reformat Ch12 conclusion
This commit is contained in:
parent
d39ebcafd9
commit
0c14301597
@ -63,7 +63,7 @@ Unfortunately, today, you probably associate the term "`REST`" with JSON APIs, s
|
|||||||
used in industry. This is a misapplied use of the term REST because JSON is not a _natural_ hypermedia due to the absence of
|
used in industry. This is a misapplied use of the term REST because JSON is not a _natural_ hypermedia due to the absence of
|
||||||
hypermedia controls. The exchange of hypermedia is an explicit requirement for a system to be considered "`RESTful.`"
|
hypermedia controls. The exchange of hypermedia is an explicit requirement for a system to be considered "`RESTful.`"
|
||||||
It is a long story how we got here, using the term REST so incorrectly, and we will go into the details later in this book.
|
It is a long story how we got here, using the term REST so incorrectly, and we will go into the details later in this book.
|
||||||
But, for now, if you currently think "`REST == JSON`", please try to set that understanding aside while reading this book,
|
But, for now, if you think REST implies JSON, please try to set that understanding aside while reading this book,
|
||||||
and come to the concept with fresh eyes.
|
and come to the concept with fresh eyes.
|
||||||
|
|
||||||
It is important to understand that, in his dissertation, Fielding was describing The World Wide Web as it existed in the
|
It is important to understand that, in his dissertation, Fielding was describing The World Wide Web as it existed in the
|
||||||
|
|||||||
@ -275,7 +275,7 @@ and are often perfectly happy with the results.
|
|||||||
|
|
||||||
These two tags give a tremendous amount of expressive power to HTML.
|
These two tags give a tremendous amount of expressive power to HTML.
|
||||||
|
|
||||||
=== So What _Isn't_ Hypermedia?
|
=== So What Isn't Hypermedia?
|
||||||
|
|
||||||
So links and forms are the two main hypermedia-based mechanisms for interacting with a server available in HTML.
|
So links and forms are the two main hypermedia-based mechanisms for interacting with a server available in HTML.
|
||||||
|
|
||||||
|
|||||||
@ -221,7 +221,7 @@ into this category. We will note when a feature is progressive enhancement frie
|
|||||||
Ultimately, it is up to you, the developer, to decide if the trade-offs of progressive enhancement (a more basic UX,
|
Ultimately, it is up to you, the developer, to decide if the trade-offs of progressive enhancement (a more basic UX,
|
||||||
limited improvements over plain HTML) are worth the benefits for your application users.
|
limited improvements over plain HTML) are worth the benefits for your application users.
|
||||||
|
|
||||||
=== Adding `hx-boost` to Contact.app
|
=== Adding "`hx-boost`" to Contact.app
|
||||||
|
|
||||||
For the contact app we are building, we want this htmx "`boost`" behavior... well, everywhere.
|
For the contact app we are building, we want this htmx "`boost`" behavior... well, everywhere.
|
||||||
|
|
||||||
|
|||||||
@ -418,13 +418,13 @@ https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching[MDN article on the top
|
|||||||
documentation] discusses this issue as well.
|
documentation] discusses this issue as well.
|
||||||
****
|
****
|
||||||
|
|
||||||
=== Updating The Navigation Bar With `hx-push-url`
|
=== Updating the Navigation Bar With "`hx-push-url`"
|
||||||
|
|
||||||
One shortcoming of our current Active Search implementation, when compared with the normal form submission, is that when
|
One shortcoming of our current Active Search implementation, when compared with the normal form submission, is that when
|
||||||
you submit the form version it updates the navigation bar of the browser to include the search term. So, for example, if
|
you submit the form version it updates the navigation bar of the browser to include the search term. So, for example, if
|
||||||
you search for "`joe`" in the search box, you will end up with a url that looks like this in your browser's nav bar:
|
you search for "`joe`" in the search box, you will end up with a url that looks like this in your browser's nav bar:
|
||||||
|
|
||||||
.The Updated Location After A Form Search
|
.The updated location after a form search
|
||||||
----
|
----
|
||||||
https://example.com/contacts?q=joe
|
https://example.com/contacts?q=joe
|
||||||
----
|
----
|
||||||
|
|||||||
@ -501,7 +501,7 @@ bar appears. When the progress bar reaches 100%, it disappears and a link to do
|
|||||||
can then click on that link and download their archive. A nice, polished user experience when compared with the common
|
can then click on that link and download their archive. A nice, polished user experience when compared with the common
|
||||||
click-and-wait experience of many websites.
|
click-and-wait experience of many websites.
|
||||||
|
|
||||||
== Smoothing Things Out: Animations in htmx
|
== Smoothing Things Out: Animations in Htmx
|
||||||
|
|
||||||
As nice as this UI is, there is one minor annoyance with it: as the progress bar updates it "`jumps`" from one position
|
As nice as this UI is, there is one minor annoyance with it: as the progress bar updates it "`jumps`" from one position
|
||||||
to the next. This looks jerky and is reminiscent of the feel of a full page refresh in web 1.0 style applications. It
|
to the next. This looks jerky and is reminiscent of the feel of a full page refresh in web 1.0 style applications. It
|
||||||
@ -523,7 +523,7 @@ with their SPA counterparts: it is hard to use CSS transitions without using som
|
|||||||
|
|
||||||
This is unfortunate, but htmx rectifies this situation with its swapping model. Let's look at how.
|
This is unfortunate, but htmx rectifies this situation with its swapping model. Let's look at how.
|
||||||
|
|
||||||
=== The "`Settling`" Step in htmx
|
=== The "`Settling`" Step in Htmx
|
||||||
|
|
||||||
When we discussed the htmx swap model in Chapter 5, we focused on the classes that htmx adds and removes, but we skipped
|
When we discussed the htmx swap model in Chapter 5, we focused on the classes that htmx adds and removes, but we skipped
|
||||||
over the idea of "`settling`". What is "`settling`" in htmx terms? Settling is the following process: when htmx is
|
over the idea of "`settling`". What is "`settling`" in htmx terms? Settling is the following process: when htmx is
|
||||||
@ -542,14 +542,14 @@ So, in our case, all we need to do is to add a stable ID to our `progress-bar` e
|
|||||||
on every update, the progress bar should smoothly move across the screen as it is updating, using the CSS transition
|
on every update, the progress bar should smoothly move across the screen as it is updating, using the CSS transition
|
||||||
defined in our style sheet:
|
defined in our style sheet:
|
||||||
|
|
||||||
.Smoothing Things Out
|
.Smoothing things out
|
||||||
[source, html]
|
[source, html]
|
||||||
----
|
----
|
||||||
<div class="progress" >
|
<div class="progress" >
|
||||||
<div id="archive-progress" class="progress-bar" style="width:{{ archiver.progress() * 100 }}%"></div> <1>
|
<div id="archive-progress" class="progress-bar" style="width:{{ archiver.progress() * 100 }}%"></div> <1>
|
||||||
</div>
|
</div>
|
||||||
----
|
----
|
||||||
<1> The progress bar div now has a stable id across requests
|
<1> The progress bar div now has a stable id across requests.
|
||||||
|
|
||||||
So, despite all the complicated mechanics going on behind the scenes in htmx, all we have to do, as an htmx user,
|
So, despite all the complicated mechanics going on behind the scenes in htmx, all we have to do, as an htmx user,
|
||||||
is add a stable `id` attribute to the element we want to animate.
|
is add a stable `id` attribute to the element we want to animate.
|
||||||
|
|||||||
@ -21,7 +21,7 @@ It requires different trade-offs and design decisions.
|
|||||||
Nonetheless, the concepts of hypermedia, HATEOAS, and REST can be directly applied to build delightful mobile applications!
|
Nonetheless, the concepts of hypermedia, HATEOAS, and REST can be directly applied to build delightful mobile applications!
|
||||||
|
|
||||||
|
|
||||||
== The state of mobile app development
|
== The State of Mobile App Development
|
||||||
Before we can discuss how to apply hypermedia to mobile platforms, we need to understand how native mobile apps are commonly built.
|
Before we can discuss how to apply hypermedia to mobile platforms, we need to understand how native mobile apps are commonly built.
|
||||||
I'm using the word "`native`" to refer to code written against an SDK provided by the phone's operating system (typically Android or iOS).
|
I'm using the word "`native`" to refer to code written against an SDK provided by the phone's operating system (typically Android or iOS).
|
||||||
This code is packaged into an executable binary, and uploaded & approved through app stores controlled by Google and Apple.
|
This code is packaged into an executable binary, and uploaded & approved through app stores controlled by Google and Apple.
|
||||||
@ -74,7 +74,7 @@ There are two approaches employing hypermedia to build & ship native mobile apps
|
|||||||
- Hyperview, a new hypermedia format we designed specifically for mobile apps
|
- Hyperview, a new hypermedia format we designed specifically for mobile apps
|
||||||
|
|
||||||
|
|
||||||
=== Web views
|
=== Web Views
|
||||||
The simplest way to use hypermedia architecture on mobile is by leveraging web technologies.
|
The simplest way to use hypermedia architecture on mobile is by leveraging web technologies.
|
||||||
Both Android and iOS SDKs provide "`web views`": chromeless web browsers that can be embedded in native apps.
|
Both Android and iOS SDKs provide "`web views`": chromeless web browsers that can be embedded in native apps.
|
||||||
Tools like Apache Cordova make it easy to take the URL of a website, and spit out native iOS and Android apps based on web views.
|
Tools like Apache Cordova make it easy to take the URL of a website, and spit out native iOS and Android apps based on web views.
|
||||||
@ -212,7 +212,7 @@ HXML responses remain pure, with UI and interactions represented in declarative
|
|||||||
****
|
****
|
||||||
|
|
||||||
|
|
||||||
=== Which Hypermedia architecture should you use?
|
=== Which Hypermedia Architecture Should You Use?
|
||||||
|
|
||||||
We've discussed two approaches for creating mobile apps using Hypermedia architecture:
|
We've discussed two approaches for creating mobile apps using Hypermedia architecture:
|
||||||
|
|
||||||
@ -225,10 +225,10 @@ Both approaches solve the fundamental issues with traditional, SPA-like mobile a
|
|||||||
|
|
||||||
- The backend controls the full state of the app.
|
- The backend controls the full state of the app.
|
||||||
- Our app's logic is all in one place.
|
- Our app's logic is all in one place.
|
||||||
- The app always runs the latest version, there's no API churn to worry about
|
- The app always runs the latest version, there's no API churn to worry about.
|
||||||
|
|
||||||
So which approach should you use for a Hypermedia-driven mobile app?
|
So which approach should you use for a Hypermedia-driven mobile app?
|
||||||
Based on my experience building both types of apps, we strongly believe the Hyperview approach results in a better user experience.
|
Based on our experience building both types of apps, we strongly believe the Hyperview approach results in a better user experience.
|
||||||
The web-view will always feel out-of-place on iOS and Android; there's just no good way to replicate the patterns of navigation and interaction that mobile users expect.
|
The web-view will always feel out-of-place on iOS and Android; there's just no good way to replicate the patterns of navigation and interaction that mobile users expect.
|
||||||
Hyperview was created specifically to address the limitations of thick-client and web view approaches.
|
Hyperview was created specifically to address the limitations of thick-client and web view approaches.
|
||||||
After the initial investment to learn Hyperview, you'll get all of the benefits of the Hypermedia architecture, without the downsides of a degraded user experience.
|
After the initial investment to learn Hyperview, you'll get all of the benefits of the Hypermedia architecture, without the downsides of a degraded user experience.
|
||||||
@ -1028,7 +1028,7 @@ This UI allows sharing URLs and messages from one app to another app.
|
|||||||
Hyperview has a `share` action to support this interaction.
|
Hyperview has a `share` action to support this interaction.
|
||||||
It involves a custom namespace, and share-specific attributes.
|
It involves a custom namespace, and share-specific attributes.
|
||||||
|
|
||||||
.System Share action
|
.System share action
|
||||||
[source,xml]
|
[source,xml]
|
||||||
----
|
----
|
||||||
<behavior
|
<behavior
|
||||||
@ -1110,7 +1110,7 @@ In the next chapter, we will create a custom behavior action to enhance our mobi
|
|||||||
|
|
||||||
We've already seen the simplest type of trigger, a `press` on an element. Hyperview supports many other common triggers used in mobile apps.
|
We've already seen the simplest type of trigger, a `press` on an element. Hyperview supports many other common triggers used in mobile apps.
|
||||||
|
|
||||||
===== longPress
|
===== Long-press
|
||||||
Closely related to a press is a long-press.
|
Closely related to a press is a long-press.
|
||||||
A behavior with `trigger="longPress"` will trigger when the user presses and holds on the element.
|
A behavior with `trigger="longPress"` will trigger when the user presses and holds on the element.
|
||||||
"`Long-press`" interactions are often used for shortcuts and power features.
|
"`Long-press`" interactions are often used for shortcuts and power features.
|
||||||
@ -1135,7 +1135,7 @@ This is a contrived example for the sake of brevity.
|
|||||||
A better UX would be for the long-press to bring up a contextual menu of shortcuts and advanced options.
|
A better UX would be for the long-press to bring up a contextual menu of shortcuts and advanced options.
|
||||||
This could be achieved by using `action="alert"` and opening a system dialog box with the shortcuts.
|
This could be achieved by using `action="alert"` and opening a system dialog box with the shortcuts.
|
||||||
|
|
||||||
===== load
|
===== Load
|
||||||
Sometimes we want an action to trigger as soon as the screen loads.
|
Sometimes we want an action to trigger as soon as the screen loads.
|
||||||
`trigger="load"` does exactly this.
|
`trigger="load"` does exactly this.
|
||||||
One use case is to quickly load a shell of the screen, and then fill in the main content on the screen with a second update action.
|
One use case is to quickly load a shell of the screen, and then fill in the main content on the screen with a second update action.
|
||||||
@ -1163,13 +1163,13 @@ As soon as this screen loads, the behavior with `trigger="`load`"` fires off the
|
|||||||
It requests content from the `/content` path and replaces the container view with the response.
|
It requests content from the `/content` path and replaces the container view with the response.
|
||||||
|
|
||||||
|
|
||||||
===== visible
|
===== Visible
|
||||||
Unlike `load`, the `visible` trigger will only execute the behavior when the element with the behavior is scrolled into the viewport on the mobile device.
|
Unlike `load`, the `visible` trigger will only execute the behavior when the element with the behavior is scrolled into the viewport on the mobile device.
|
||||||
The `visible` action is commonly used to implement an infinite-scroll interaction on a `<list>` of `<item>` elements.
|
The `visible` action is commonly used to implement an infinite-scroll interaction on a `<list>` of `<item>` elements.
|
||||||
The last item in the list includes a behavior with `trigger="visible"`.
|
The last item in the list includes a behavior with `trigger="visible"`.
|
||||||
The `append` action will fetch the next page of items and append them to the list.
|
The `append` action will fetch the next page of items and append them to the list.
|
||||||
|
|
||||||
===== refresh
|
===== Refresh
|
||||||
This trigger captures a "`pull to refresh`" action on `<list>` and `<view>` items.
|
This trigger captures a "`pull to refresh`" action on `<list>` and `<view>` items.
|
||||||
This interaction is associated with fetching up-to-date content from the backend.
|
This interaction is associated with fetching up-to-date content from the backend.
|
||||||
Thus, it's typically paired with an update or reload action to show the latest data on the screen.
|
Thus, it's typically paired with an update or reload action to show the latest data on the screen.
|
||||||
@ -1184,12 +1184,12 @@ Thus, it's typically paired with an update or reload action to show the latest d
|
|||||||
</view>
|
</view>
|
||||||
</body>
|
</body>
|
||||||
----
|
----
|
||||||
<1> When the view is pulled down to refresh, reload the screen
|
<1> When the view is pulled down to refresh, reload the screen.
|
||||||
|
|
||||||
Note that adding a behavior with `trigger="refresh"` to a `<view>` or `<list>` will add the pull-to-refresh interaction to the element, including showing a spinner as the element is pulled down.
|
Note that adding a behavior with `trigger="refresh"` to a `<view>` or `<list>` will add the pull-to-refresh interaction to the element, including showing a spinner as the element is pulled down.
|
||||||
|
|
||||||
|
|
||||||
===== `focus`, `blur`, and `change`
|
===== Focus, blur, and change
|
||||||
These triggers are related to interactions with input elements.
|
These triggers are related to interactions with input elements.
|
||||||
Thus, they will only trigger behaviors attached to elements like `<text-field>`.
|
Thus, they will only trigger behaviors attached to elements like `<text-field>`.
|
||||||
`focus` and `blur` will trigger when the user focuses and blurs the input element, respectively.
|
`focus` and `blur` will trigger when the user focuses and blurs the input element, respectively.
|
||||||
@ -1242,13 +1242,9 @@ These concepts can be mixed together too.
|
|||||||
It's not unusual for a production Hyperview app to contain several behaviors, some triggering together and others triggering on different interactions.
|
It's not unusual for a production Hyperview app to contain several behaviors, some triggering together and others triggering on different interactions.
|
||||||
Using multiple behaviors with custom actions keeps HXML declarative, without sacrificing functionality.
|
Using multiple behaviors with custom actions keeps HXML declarative, without sacrificing functionality.
|
||||||
|
|
||||||
|
=== Quick Sketch: Elements of Hyperview
|
||||||
|
We've covered a lot of new material, so here is a quick summary of the key aspects of Hyperview:
|
||||||
|
|
||||||
== Summary
|
|
||||||
|
|
||||||
- Mobile app platforms push developers towards a thick-client architecture. But apps that use a thick client suffer from the same problems as SPAs on the web.
|
|
||||||
- Using the hypermedia architecture for mobile apps solves the problems with thick-client apps.
|
|
||||||
- HTML web views are one way to implement the hypermedia architecture for mobile apps. But HTML is not designed for mobile UIs, so this approach does not deliver a great user experience.
|
|
||||||
- Hyperview is an alternative approach to build mobile apps using the hypermedia architecture. Hyperview introduces a new format called HXML. It also provides an open-source mobile thin-client to render HXML.
|
|
||||||
- HXML looks similar to HTML, but it uses elements that correspond to mobile UIs, like `<screen>`, `<header>`, `<list>` and more.
|
- HXML looks similar to HTML, but it uses elements that correspond to mobile UIs, like `<screen>`, `<header>`, `<list>` and more.
|
||||||
- HXML also includes input elements that implement common patterns in mobile apps, such as `<switch>`, `<select-single>`, and `<select-multiple>`.
|
- HXML also includes input elements that implement common patterns in mobile apps, such as `<switch>`, `<select-single>`, and `<select-multiple>`.
|
||||||
- New UI components can be added to HXML using namespaced elements. The Hyperview client can be easily extended to render these new elements.
|
- New UI components can be added to HXML using namespaced elements. The Hyperview client can be easily extended to render these new elements.
|
||||||
@ -1257,4 +1253,14 @@ Using multiple behaviors with custom actions keeps HXML declarative, without sac
|
|||||||
- Updates to screens in Hyperview are defined using behaviors with update actions, such as `replace` and `append`.
|
- Updates to screens in Hyperview are defined using behaviors with update actions, such as `replace` and `append`.
|
||||||
- System interactions in Hyperview are defined using behaviors with system actions, such as `alert` and `share`.
|
- System interactions in Hyperview are defined using behaviors with system actions, such as `alert` and `share`.
|
||||||
- New actions can be added to HXML using namespaced attributes. The Hyperview client can be easily extended to interpret the new actions.
|
- New actions can be added to HXML using namespaced attributes. The Hyperview client can be easily extended to interpret the new actions.
|
||||||
- The extensibility of HXML and the Hyperview client make it easy for developers to define custom elements and behaviors. Developers can evolve Hyperview to suit their apps' requirements, while fully embracing the hypermedia architecture.
|
|
||||||
|
|
||||||
|
== Summary
|
||||||
|
|
||||||
|
Mobile app platforms push developers towards a thick-client architecture. But apps that use a thick client suffer from the same problems as SPAs on the web. Using the hypermedia architecture for mobile apps can solve these problems.
|
||||||
|
|
||||||
|
One way to implement the hypermedia architecture for mobile apps is with HTML web views. But HTML is not designed for mobile UIs, so this approach does not deliver a great user experience.
|
||||||
|
|
||||||
|
Hyperview offers an alternative approach using the hypermedia architecture, based on a new format called HXML. It also provides an open-source mobile thin-client to render HXML. Again, HXML looks similar to HTML, but it uses elements and patterns that correspond to mobile UIs.
|
||||||
|
|
||||||
|
The extensibility of HXML and the Hyperview client make it easy to define custom elements and behaviors. Developers can evolve Hyperview to suit their apps' requirements, while fully embracing the hypermedia architecture.
|
||||||
|
|||||||
@ -65,7 +65,7 @@ Select an option based on which developer SDK you have installed.
|
|||||||
(The screenshots in this chapter will be taken from the iOS simulator.)
|
(The screenshots in this chapter will be taken from the iOS simulator.)
|
||||||
With any luck, you will see the Expo mobile app installed in the simulator.
|
With any luck, you will see the Expo mobile app installed in the simulator.
|
||||||
The mobile app will automatically launch and show a screen saying "`Network request failed.`"
|
The mobile app will automatically launch and show a screen saying "`Network request failed.`"
|
||||||
That's because by default, this app is configured to make a request to `http://0.0.0.0:8085/index.xml`, but our backend is listening on port 5000.
|
That's because by default, this app is configured to make a request to \http://0.0.0.0:8085/index.xml, but our backend is listening on port 5000.
|
||||||
To fix this, we can make a simple configuration change in the `demo/src/constants.js` file:
|
To fix this, we can make a simple configuration change in the `demo/src/constants.js` file:
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
@ -77,7 +77,7 @@ export const ENTRY_POINT_URL = 'http://0.0.0.0:5000/'; <2>
|
|||||||
<2> Setting the URL to point to our contacts app
|
<2> Setting the URL to point to our contacts app
|
||||||
|
|
||||||
We're not up and running yet.
|
We're not up and running yet.
|
||||||
With our Hyperview client now pointing to the right endpoint, we see a different error, a "`ParseError`".
|
With our Hyperview client now pointing to the right endpoint, we see a different error, a "`ParseError.`"
|
||||||
That's because the backend is responding to requests with HTML content, but the Hyperview client expects an XML response (specifically, HXML).
|
That's because the backend is responding to requests with HTML content, but the Hyperview client expects an XML response (specifically, HXML).
|
||||||
So it's time to turn our attention to our Flask backend.
|
So it's time to turn our attention to our Flask backend.
|
||||||
We will go through the Flask views, and replace the HTML templates with HXML templates.
|
We will go through the Flask views, and replace the HTML templates with HXML templates.
|
||||||
@ -100,7 +100,7 @@ Every other action the user can take will be declared in the HXML of that first
|
|||||||
This minimal configuration is one elegant aspect of the Hypermedia-driven architecture!
|
This minimal configuration is one elegant aspect of the Hypermedia-driven architecture!
|
||||||
|
|
||||||
Of course, you may want to write more on-device code to support more features in your mobile app.
|
Of course, you may want to write more on-device code to support more features in your mobile app.
|
||||||
We will demonstrate how to do that later in this chapter, in the section called "`Extending the Client`".
|
We will demonstrate how to do that later in this chapter, in the section called "`Extending the Client.`"
|
||||||
****
|
****
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -294,7 +294,7 @@ export default class HyperviewScreen extends PureComponent {
|
|||||||
// ... omitted for brevity
|
// ... omitted for brevity
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
<1> Import the show-toast action
|
<1> Import the show-toast action.
|
||||||
<2> Pass the action to the `Hyperview` component, as a prop called `behaviors`.
|
<2> Pass the action to the `Hyperview` component, as a prop called `behaviors`.
|
||||||
|
|
||||||
All that's left to do is trigger the `show-toast` action from our HXML.
|
All that's left to do is trigger the `show-toast` action from our HXML.
|
||||||
@ -369,7 +369,7 @@ By using a custom action, the toast UI remains visible even while the screens ch
|
|||||||
image::screenshot_hyperview_toast.png["Small gray box shows at top of screen: 'Deleted Contact!'"]
|
image::screenshot_hyperview_toast.png["Small gray box shows at top of screen: 'Deleted Contact!'"]
|
||||||
|
|
||||||
|
|
||||||
== Swipe gesture on Contacts
|
== Swipe Gesture on Contacts
|
||||||
To add communication capabilities and the toast UI, we extended the client with custom behavior actions.
|
To add communication capabilities and the toast UI, we extended the client with custom behavior actions.
|
||||||
But the Hyperview client can also be extended with custom UI components that render on the screen.
|
But the Hyperview client can also be extended with custom UI components that render on the screen.
|
||||||
Custom components are implemented as React Native components.
|
Custom components are implemented as React Native components.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user