Josselin Dionisi - Freelance developer

Discovering Widgets with React Native on iOS

ionicons-v5-k Josselin Dionisi Feb 3, 2025
92 reads Level: Confirmed

Well, happy new year!

Admittedly, I'm a little late in wishing you a happy new year, but January is always the month for getting back into the swing of things, planning for the year and getting back in touch with just about everyone. Not to mention the galettes ... anyway 😛

Today I wanted to talk about a handy little tool that appeared on iOS 14: widgets.

Personally, I use them a lot for apps that give me info at a glance like the weather, the day's to-do list, the calendar, etc ...

It's really handy and naturally I wanted to know "but how does it work"?

You can't do it again 😀. So I stuck my nose into the code and here's what I can tell you.

Creating a native widget

As you'd expect, React Native can do a lot of things for us, but it does have its limits. Here we're talking about creating a widget that runs on the phone directly, and unfortunately we won't be able to develop it directly in Javascript/Typescript via RN. So you'll need to open Xcode and be prepared to do a bit of Swift/Objective-C.

Don't worry, it's a very easy language for a web developer to learn, and you'll quickly get the hang of the syntax.

But first we're going to use the template provided by Xcode directly.

Simply go to File > New > Target and select "Widget Extension".

You'll get the generated files and a functional widget displaying an emoji and the current time.

Perfect! That's half of what we want 😛

Now we need to be able to connect our widget to the base application, and to do that we're going to place them in the same group.

Add a capability to the 2 projects as follows:

Select App Groups and give it a recognizable name

Repeat exactly the same operation on the Target corresponding to the Widget (here "CryptoWidgetExtension").

Your widget is now linked to your application. 🙂

Making our widget dynamic

To display a value that changes regularly, I've chosen to display the value of Bitcoin in Euro (it's been in the news a lot lately, I think).

There are several ways of doing this:

  • Call an API from the widget, which returns the price to be displayed.
  • Call the API from our React Native application, which will then send the value to our widget.

Let's start from the simplest and do the first

We'll add a swift method to our widget to retrieve the price from an API:

Now we need to adapt our widget to take this value into account:

Most of this code is already provided when the widget is initialized. All I did was add the bitcoinPrice value to each part of the configuration and to the final view, so as to have an insert displaying "Bitcoin Price" followed by the value.

You can now launch the application and you'll see the value from the API displayed on the widget. 😛

"Ok great but how do I update this regularly so it's up to date?"

Well, my answer is that you already do. In iOS it is planned that widgets are refreshed regularly (about 15 minutes) in order to both have correct data but also preserve memory and battery. It's well done, isn't it? 😀

Building a bridge between React Native and iOS

Well, that's all well and good, but as things stand we've done everything under Xcode in Swift/Objective-C. Maybe it's time for a little React Native, don't you think?

If you didn't know, there's an intermediate step to be prepared to pass functions between React Native and iOS (or Android too). It's the equivalent of a bridge between the two technologies. To do this, we're going to use Native Modules.

You can follow the full documentation here, as it perfectly answers what we want to do: store a value from React Native and make it accessible from iOS. 🙂

The part that interests us most in our case is that this value is transmitted back to the widget when it is re-actualized by the system.

To do this, we're going to add a method to our widget's code:

This method consists of telling the wiget to "get me the value written in the "myKey" key from the shared group "group.com.boreales.crypto". In other words, the value coming from the application and therefore, by extension, from React Native in our case.

Don't forget to update the function call in the timeline method written above:

On the RN side, we can imagine a method like this. The aim is to transmit a value via the NativeStorage:

Now you can clean and rebuild your application in Xcode, relaunch everything and, normally, the value displayed in the widget now comes directly from the React Native application. It's the application that makes the API call to retrieve the price, and the widget simply displays the value.

"Ok, that's cool, it works. Are we done?" Well, almost, there's still one small step missing 😛

Updating data in the background

Imagine you've installed the app, added the widget to your screen and then you go for a coffee. 15 minutes later, the time on your widget has updated but ... horror, the price of BTC has stayed the same.

Has it decided to be less volatile and calm down with age? 🤔

No, it's more a question of a "bug" in your application. In order for the value to update, the React Native application must be able to update itself regularly.

To do this, we need to use another iOS function, namely : Background Modes.

Let's go back and add this new capacity in Xcode. Then select the following two boxes:

We'll now be able to use this package:

Once again, follow the documentation and don't forget to follow the iOS-specific documentation here.

We can now adapt our React Native code to use the background functions:

That's it! Every 15 minutes or so, the application will make another call to the API via the iOS Background functions to update the stored value. Then the widget will follow its standard operation by automatically updating and re-displaying the new value, i.e. the current Bitcoin price. 🙂

It was a rather technical article with a lot of code for once, but I found it interesting the path of a data through a cross-platform language, a native application and a widget.

I'll leave you to it I hear we need to make pancakes soon! 🥞