React-Native components are awesome. But you can also extend the library yourself by creating a native component, using a bridge between the platform API (iOS, Android) and Javascript.
the community... v a r R N F S = r e q u i r e ( ' r e a c t - n a t i v e - f s ' ) ; / / C r e a t e a p a t h y o u w a n t t o w r i t e t o v a r p a t h = R N F S . D o c u m e n t D i r e c t o r y P a t h + ' / t e s t . t x t ' ; / / W r i t e t h e f i l e R N F S . w r i t e F i l e ( p a t h , ' H e l l o R e a c t - N a t i v e S y d n e y ! ' , ' u t f 8 ' ) . t h e n ( ( s u c c e s s ) = > c o n s o l e . l o g ( ' V a l a r M o r g h u l i s ! ' ) ) . c a t c h ( ( e r r ) = > c o n s o l e . l o g ( ' Y o u k n o w n o t h i n g . ' , e r r . m e s s a g e ) ) ; A le-system access by Johannes Lumpe - ★349
in... The core components (UIKit classes: View, Button, TabBar...) The community components (Camera, Maps, ActionSheet, FileSystem...) Bad luck. You'll have to build that logic in Objective-C / Java yourself...
iOS / Android component that you want to use in JS without reimplementing the logic. Lucky you. Because react-native will let you create a bridge for it.
your project, use this CLI command to generate your native component: / / I n y o u r r e a c t - n a t i v e p r o j e c t $ r e a c t - n a t i v e n e w - l i b r a r y - - n a m e M y C o m p o n e n t That will create a sample component here (not in ./Libraries?) . / n o d e _ m o d u l e s / r e a c t - n a t i v e / L i b r a r i e s / M y C o m p o n e n t
class has to extend the protocol: <RCTBridgeModule> / / M y C o m p o n e n t . h # i m p o r t " R C T B r i d g e M o d u l e . h " @ i n t e r f a c e M y C o m p o n e n t : N S O b j e c t < R C T B r i d g e M o d u l e > @ e n d That will automagically allow this class to access the React world.
class has to call the RCT_EXPORT_MODULE() macro: / / M y C o m p o n e n t . m @ i m p l e m e n t a t i o n M y C o m p o n e n t R C T _ E X P O R T _ M O D U L E ( ) ; / / D e f a u l t m o d u l e n a m e : S a m e a s c l a s s n a m e @ e n d That will allow you to access, in JS, the module named: < M y C o m p o n e n t / >
class has to call RCT_EXPORT_METHOD() macro if you want to call a method from your JS code. / / M y C o m p o n e n t . m R C T _ E X P O R T _ M E T H O D ( d o S o m e t h i n g W i t h T h a t S t r i n g : ( N S S t r i n g * ) s t r i n g ) { R C T L o g I n f o ( @ " A m a n n e e d s a s t r i n g : % @ " , s t r i n g ) ; } That will allow you to do, in JS: M y C o m p o n e n t . d o S o m e t h i n g W i t h T h a t S t r i n g ( ' H e l l o ' ) ;
to!) nally wrap our module in a React component. / / M y C o m p o n e n t . i o s . j s v a r N a t i v e C o m p o n e n t = r e q u i r e ( ' N a t i v e M o d u l e s ' ) . M y C o m p o n e n t ; v a r M y C o m p o n e n t = { d e c l a r i n g Y o u r L o v e T o : f u n c t i o n ( s t r i n g ) { / / Y o u c a n d o a c h e c k h e r e , p a s s a d e f a u l t p a r a m e t e r , e t c . . . N a t i v e C o m p o n e n t . d o S o m e t h i n g W i t h T h a t S t r i n g ( s t r i n g ) ; } } ; m o d u l e . e x p o r t s = M y C o m p o n e n t ; Finally, in your code: M y C o m p o n e n t . d e c l a r i n g Y o u r L o v e T o ( ' R e a c t N a t i v e ' ) ;
is your friend. # i m p o r t " R C T C o n v e r t . h " / / . . . R C T _ E X P O R T _ M E T H O D ( d o S o m e t h i n g W i t h T h a t C o l o r : ( N S S t r i n g * ) h e x a C o l o r ) { U I C o l o r * c o l o r = [ R C T C o n v e r t U I C o l o r : h e x a C o l o r ] ; } That will allow you to do, in JS: M y C o m p o n e n t . d o S o m e t h i n g W i t h T h a t C o l o r ( ' # 1 2 3 4 5 6 ' ) ;
return type of bridge methods is always void. If you need to get some data from a native method, you'll have to use Promises, as the bridge is asynchronous. R C T _ E X P O R T _ M E T H O D ( f i n d S o m e t h i n g A s y n c h r o n o u s , r e s o l v e r : ( R C T P r o m i s e R e s o l v e B l o c k ) r e s o l v e r e j e c t e r : ( R C T P r o m i s e R e j e c t B l o c k ) r e j e c t ) { N S A r r a y * r e s u l t s = . . . i f ( r e s u l t s ) { r e s o l v e ( r e s u l t s ) ; } e l s e { N S E r r o r * e r r o r = . . . r e j e c t ( @ " n o _ r e s u l t s " , @ " T h e r e w e r e n o r e s u l t s " , e r r o r ) ; } } That will allow you to do, in JS: M y C o m p o n e n t . f i n d S o m e t h i n g A s y n c h r o n o u s ( ) . t h e n ( ( r ) = > c o n s o l e . l o g ( r ) ) ;
Specify which thread its methods should be run on Export constants to JS Send events to JS # i m p o r t " R C T B r i d g e . h " # i m p o r t " R C T E v e n t D i s p a t c h e r . h " @ i m p l e m e n t a t i o n M y C o m p o n e n t @ s y n t h e s i z e b r i d g e = _ b r i d g e ; - ( v o i d ) m e t h o d T h a t S e n d s A n E v e n t { [ s e l f . b r i d g e . e v e n t D i s p a t c h e r s e n d A p p E v e n t W i t h N a m e : @ " C h e e s e R e m i n d e r " b o d y : @ { @ " c o n t e n t " : " I l o v e c h e e s e " } ] ; } @ e n d / / I n J S N a t i v e A p p E v e n t E m i t t e r . a d d L i s t e n e r ( ' C h e e s e R e m i n d e r ' , ( r e m i n d e r ) = > { c o n s o l e . l o g ( r e m i n d e r . c o n t e n t ) ; } ) ;
new class that extends UIView. Your manager (kind of view controller, but singleton) has now to be a subclass of RCTViewManager. / / M y C o m p o n e n t M a n a g e r . h # i m p o r t " R C T V i e w M a n a g e r . h " @ i n t e r f a c e M y C o m p o n e n t M a n a g e r : R C T V i e w M a n a g e r @ e n d
of the view. / / M y C o m p o n e n t M a n a g e r . m # i m p o r t " M y C o m p o n e n t M a n a g e r . h " # i m p o r t " M y C o m p o n e n t V i e w . h " @ i m p l e m e n t a t i o n M y C o m p o n e n t M a n a g e r R C T _ E X P O R T _ M O D U L E ( ) - ( U I V i e w * ) v i e w { r e t u r n [ [ M y C o m p o n e n t V i e w a l l o c ] i n i t ] ; } . . . / / Y o u r o t h e r R C T _ E X P O R T _ M E T H O D m e t h o d s h e r e . . . @ e n d
things in your view. / / M y C o m p o n e n t M a n a g e r . m R C T _ E X P O R T _ V I E W _ P R O P E R T Y ( l o v i n g C h e e s e , B O O L ) / / M y C o m p o n e n t V i e w . h @ i n t e r f a c e M y C o m p o n e n t V i e w : U I V i e w @ p r o p e r t y ( n o n a t o m i c , a s s i g n ) b o o l l o v i n g C h e e s e ; @ e n d / / M y C o m p o n e n t . i o s . j s M y C o m p o n e n t . p r o p T y p e s = { l o v i n g C h e e s e : R e a c t . P r o p T y p e s . b o o l , } ;
It's really cool to publish something to npm The frequent changes to the API forces you to be reactive It's harder than I thought to get feedbacks & contributions
Yet. Facebook has created a great tool to allow us extend their tool. If you have to build your own, check the docs regularly. Don't be afraid of native code.
View Components (by Brent Vatne) Building Custom React Native Components From Scratch (by Jay Garcia) How to Bridge an Objective-C View Component (by Jason Brown) Awesome React-Native JS.Coach