Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Designing and maintaining an open-source React Native library

Designing and maintaining an open-source React Native library

Mathieu Acthernoene

October 14, 2021
Tweet

More Decks by Mathieu Acthernoene

Other Decks in Technology

Transcript

  1. What's the bridge for? Reading sync data using constants, Calling

    async methods using promises or callbacks, Receiving events using event listeners
  2. What's the bridge for? Reading sync data using constants, Calling

    async methods using promises or callbacks, Receiving events using event listeners
  3. - (NSDictionary *)constantsToExport { return @{ @"initialTimeZone": [[NSTimeZone localTimeZone] name],

    }; } Objective-C TypeScript import { NativeModules } from "react-native"; const NativeModule: Readonly<{ initialTimeZone: string; }> = NativeModules.RNModuleTemplate; export const initialTimeZone = NativeModule.initialTimeZone;
  4. @Override public @Nullable Map<String, Object> getConstants() { HashMap<String, Object> constants

    = new HashMap<>(); constants.put("initialTimeZone", TimeZone.getDefault().getID()); return constants; } Java TypeScript import { NativeModules } from "react-native"; const NativeModule: Readonly<{ initialTimeZone: string; }> = NativeModules.RNModuleTemplate; export const initialTimeZone = NativeModule.initialTimeZone;
  5. What's the bridge for? Reading sync data using constants, Calling

    async methods using promises or callbacks, Receiving events using event listeners
  6. RCT_EXPORT_METHOD( getTimeZone:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject ) { @try { resolve([[NSTimeZone localTimeZone] name]);

    } @catch (NSException *exception) { reject(@"error_code", exception.reason, nil); } } import { NativeModules } from "react-native"; const NativeModule: Readonly<{ getTimeZone: () = > Promise<string>; }> = NativeModules.RNModuleTemplate; export function getTimeZone(): Promise<string> { return NativeModule.getTimeZone(); } Objective-C TypeScript
  7. @ReactMethod public void getTimeZone(Promise promise) { try { promise.resolve(TimeZone.getDefault().getID()); }

    catch (Exception exception) { promise.reject("error_code", exception.getMessage()); } } Java import { NativeModules } from "react-native"; const NativeModule: Readonly<{ getTimeZone: () = > Promise<string>; }> = NativeModules.RNModuleTemplate; export function getTimeZone(): Promise<string> { return NativeModule.getTimeZone(); } TypeScript
  8. What's the bridge for? Reading sync data using constants, Calling

    async methods using promises or callbacks, Receiving events using event listeners
  9. - (void)startObserving { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onTimeZoneChange) name:NSSystemTimeZoneDidChangeNotification object:nil]; }

    - (void)stopObserving { [[NSNotificationCenter defaultCenter] removeObserver:self name:NSSystemTimeZoneDidChangeNotification object:nil]; } - (NSArray<NSString * > *)supportedEvents { return @[@"timeZoneChange"]; } - (void)onTimeZoneChange { [self sendEventWithName:@"timeZoneChange" body:@{ @"date": [[NSISO8601DateFormatter new] stringFromDate:[NSDate date]], @"value": [[NSTimeZone localTimeZone] name], }]; } Objective-C import { NativeEventEmitter, NativeModules } from "react-native"; const emitter = new NativeEventEmitter(NativeModules.RNModuleTemplate); type Listeners = { timeZoneChange: (body: { date: string; value: string }) = > void; }; export function addListener<Type extends keyof Listeners>( type: Type, listener: Listeners[Type], ): () = > void { const subscription = emitter.addListener(type, listener); return subscription.remove; } TypeScript
  10. WritableMap body = Arguments.createMap(); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());

    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); body.putString("date", dateFormat.format(new Date())); body.putString("value", TimeZone.getDefault().getID()); getReactApplicationContext() .getJSModule(RCTDeviceEventEmitter.class) .emit("timeZoneChange", body); import { NativeEventEmitter, NativeModules } from "react-native"; const emitter = new NativeEventEmitter(NativeModules.RNModuleTemplate); type Listeners = { timeZoneChange: (body: { date: string; value: string }) = > void; }; export function addListener<Type extends keyof Listeners>( type: Type, listener: Listeners[Type], ): () = > void { const subscription = emitter.addListener(type, listener); return subscription.remove; } Java TypeScript
  11. Know what you want to maintain Why not a PHILOSOPHY

    ( .md)? You think it belongs to module core You think it doesn't Consider the PR Feel free to refuse (and explain nicely why)
  12. Think about: React Native updates and breaking changes iOS updates

    and breaking changes Android updates and breaking changes macOS updates and breaking changes Windows updates and breaking changes RNW updates and breaking changes React updates and breaking changes …
  13. Embrace help 🤝 Even if they don't know the tech,

    people can help you (triage, linking to similar issues, asking for more details, etc.)