iOS Today Widget in React Native

License: Other

Language: Ruby

Keywords: ios, ios-extension, react-native, react-native-ios, today-widget, widget

React Native Today Widget

Experimental library investigating limits of implementation iOS App Extensions using React Native.

Sample result from Complex example:


What is Today Widget?

Getting started

This library will help you to add iOS Today Widget App Extension without need to open XCode.


  • xcodeproj for linking script:
$ gem install xcodeproj

You may need to use sudo gem install xcodeproj or sudo gem install -n /usr/local/bin xcodeproj depends on your Ruby installation.

  • For React Native compatibility, check peerDependencies in package.json


$ yarn add react-native-today-widget
$ react-native link

You could use $ npm i react-native-today-widget --save as well, but don't forget to save it in package.json dependencies. Otherwise RN will not link it.

Whenever you change Bundle Identifier (CFBundleIdentifier) for main app, you have to run ./node_modules/.bin/bundle-id script or reinstall the module (rm -rf node_modules/react-native-today-widget && yarn)

Manual linking

react-native link should works, but in case of some troubles, you could follow general guide for linking libraries.

  • file for Step 1 is /node_modules/react-native-today-widget/ios/RNTodayWidgetExtension.xcodeproj
  • as a Step 2, add TodayWidgetExtension.appex to Embedded Binaries on the General tab for your main target
  • in Step 3, add $(SRCROOT)/../node_modules/react-native-today-widget/ios/TodayWidgetExtension to Header Search Paths


All you need is to create an index.widget.js file at the root and register there your component for key TodayWidgetExtension:

const TodayWidget = () => (
      Hello Today Widget!

AppRegistry.registerComponent('TodayWidgetExtension', () => TodayWidget);

Please note that registering both the widget and the main app in index.js file can cause memory issues. Because the app is also bundled (even if you don't use it in your widget), and it causes 'Unable to load' error. When we split the registration into two different files, the widget and the main app are bundled seperately. See blog post from Maxim Toyberman.

In place of TodayWidget component, you could use any JSX component. See Basic example.

Run your app as usual:

react-native run-ios

Display new widget on Search screen or by force touch on your app icon (on devices supporting 3D Touch).

If you need to see logs from TodayWidgetExtension, use:

react-native log-ios

In your extension scheme’s Run phase, you specify a host app as the executable

Memory limitation

The memory limit for Today Widget on device is 16 MB. (Great explanation is in this talk by Conrad Kramer)

Verified experimentally using XCode debugger - while loading big image, Today Widget crashes as soon as it reaches 16 MB memory usage.

Memory usage of Basic example with just one Text element is about 11 MB. Up to 13 MB during content rendering.

For running Today Widget on device you have to use Release build configuration. Development mode adds too much overhead. Only possibility to run the widget on device in development mode is using Instruments tool to temporarily disable the limit.


To investigate more iOS App Extensions with React Native check those:

API Reference


Default dev menu is not available in widget, but you could use DevSettings from NativeModules or this prepared DevMenu component to enable Live/Hot reload or remote JS debugging.

  • children - trigger element (TouchableOpacity by default)
  • style - overriding default style for trigger element
  • title - set trigger text ('DM' by default)
import { DevMenu } from 'react-native-today-widget';

const TodayWidget = () => (
    <Text>Hello Today Widget!</Text>
    {__DEV__ && <DevMenu />
      /* Has to be a last element to be clickable,
      because it has absolute position */

Screenshot of opened Developer Menu:



Asks the system open a URL on behalf of the currently running app extension.

  • url - the URL to open

If you employ this method to open other apps from your widget, your App Store submission might entail additional review to ensure compliance with the intent of widgets.

setExpandable([expandable:boolean = true], [maxHeight:number = 110])

Enables to display native Show More / Less button in top right corner of the widget (iOS 10).

  • expandable - if false Show More / Less button is hidden
  • maxHeight - height of expanded widget

Height of collapsed Today Widget is always 110px on iOS 10.

import { setExpandable } from 'react-native-today-widget';

const TodayWidget = () => {
  const isExpandable = true;
  const maxHeight = 500;
  setExpandable(isExpandable, maxHeight);
  const onLayout = (event) => {
    const height = event.nativeEvent.layout.height;
    if (height <= 110) {
      console.log('widget is in compact mode');
    else if (height > 110) {
      console.log('widget is in expanded mode');
  return (
    <View onLayout={onLayout}>
        Hello Today Widget!

You could try Expandable example

Project Statistics

Sourcerank 5
Repository Size 2.95 MB
Stars 127
Forks 8
Watchers 4
Open issues 9
Dependencies 2,156
Contributors 1
Tags 27
Last updated
Last pushed

Top Contributors See all

Matěj Kříž

Packages Referencing this Repo

Today Widget extension (iOS) development using React Native
Latest release 1.0.0 - Updated - 127 stars

Recent Tags See all

v0.10.1 December 28, 2017
v0.10.0 December 28, 2017
v0.9.1 December 03, 2017
v0.9.0 December 02, 2017
v0.9.0 December 02, 2017
v0.8.1 November 03, 2017
v0.8.0 November 03, 2017
v0.7.1 September 10, 2017
v0.7.0 September 10, 2017
v0.6.5 August 11, 2017
v0.6.4 June 25, 2017
v0.6.3 June 10, 2017
v0.6.2 June 09, 2017
v0.6.1 June 09, 2017
v0.6.0 June 09, 2017

Something wrong with this page? Make a suggestion

Last synced: 2018-06-03 13:58:57 UTC

Login to resync this repository