diff --git a/Examples/Tests/index.ios.js b/Examples/Tests/index.ios.js
index 964208110deed169035368ca3d019fad6f091d9e..fa78cea0128e346b980aa3103228f625f41391f2 100644
--- a/Examples/Tests/index.ios.js
+++ b/Examples/Tests/index.ios.js
@@ -13,8 +13,20 @@ const HelloGL = require("./HelloGL");
 const Display2 = require("./Display2");
 const { width: viewportW, height: viewportH } = require("Dimensions").get("window");
 
-const Tests = React.createClass({
-  render: function() {
+class Tests extends React.Component {
+
+  constructor (props) {
+    super(props);
+    this.onLoad = this.onLoad.bind(this);
+    this.onProgress = this.onProgress.bind(this);
+  }
+  onLoad () {
+    console.log("LOADED");
+  }
+  onProgress ({nativeEvent: { progress, loaded, total }}) {
+    console.log("PROGRESS", progress, loaded, total);
+  }
+  render () {
     const helloGL =
       ;
 
@@ -48,7 +60,7 @@ const Tests = React.createClass({
       ;
 
     return 
-      
+      
         
           
             {txt}
@@ -68,6 +80,6 @@ const Tests = React.createClass({
       
     ;
   }
-});
+}
 
 AppRegistry.registerComponent("Tests", () => Tests);
diff --git a/RNGL/GLCanvas.h b/RNGL/GLCanvas.h
index 2618cb7ef54cf06a955793a7715b2007e0fbed1e..7a8019e0f5da225a9365ba0f7f3f90a103d6c229 100644
--- a/RNGL/GLCanvas.h
+++ b/RNGL/GLCanvas.h
@@ -8,8 +8,10 @@
 @property (nonatomic) NSNumber *nbContentTextures;
 @property (nonatomic) NSNumber *renderId;
 @property (nonatomic) NSArray *imagesToPreload;
+@property (nonatomic, assign) BOOL onProgress;
+@property (nonatomic, assign) BOOL onLoad;
 
 - (instancetype)initWithBridge:(RCTBridge *)bridge
-                   withContext:(EAGLContext*)context;
+                   withContext:(EAGLContext *)context;
 
 @end
diff --git a/RNGL/GLCanvas.m b/RNGL/GLCanvas.m
index 9e354ae969dcce0a4a37da9a87741005fc32aab2..a501b60c439b4a2c07b52a6bda8974fcfe1ef942 100644
--- a/RNGL/GLCanvas.m
+++ b/RNGL/GLCanvas.m
@@ -2,6 +2,7 @@
 #import "RCTBridge.h"
 #import "RCTUtils.h"
 #import "RCTConvert.h"
+#import "RCTEventDispatcher.h"
 #import "RCTLog.h"
 #import "GLCanvas.h"
 #import "GLShader.h"
@@ -9,6 +10,7 @@
 #import "GLTexture.h"
 #import "GLImage.h"
 #import "GLRenderData.h"
+#import "UIView+React.h"
 
 // For reference, see implementation of gl-shader's GLCanvas
 
@@ -32,7 +34,7 @@
 }
 
 - (instancetype)initWithBridge:(RCTBridge *)bridge
-                   withContext:(EAGLContext*)context
+                   withContext:(EAGLContext *)context
 {
   if ((self = [super init])) {
     _bridge = bridge;
@@ -50,11 +52,35 @@ RCT_NOT_IMPLEMENTED(-init)
 {
   if (_preloadingDone) return;
   if ([imagesToPreload count] == 0) {
+    [self dispatchOnLoad];
     _preloadingDone = true;
   }
+  else {
+    _preloadingDone = false;
+  }
   _imagesToPreload = imagesToPreload;
 }
 
+- (void)dispatchOnLoad
+{
+  if (_onLoad) {
+    [_bridge.eventDispatcher sendInputEventWithName:@"load" body:@{ @"target": self.reactTag }];
+  }
+}
+
+- (void)dispatchOnProgress: (double)progress withLoaded:(int)loaded withTotal:(int)total
+{
+  if (_onProgress) {
+    NSDictionary *event =
+  @{
+    @"target": self.reactTag,
+    @"progress": @(progress),
+    @"loaded": @(loaded),
+    @"total": @(total) };
+    [_bridge.eventDispatcher sendInputEventWithName:@"progress" body:event];
+  }
+}
+
 - (void)setOpaque:(BOOL)opaque
 {
   _opaque = opaque;
@@ -203,20 +229,26 @@ NSString* srcResource (id res)
   }
 }
 
-- (bool)allPreloaded
+- (int)countPreloaded
 {
+  int nb = 0;
   for (id toload in _imagesToPreload) {
-    if (![_preloaded containsObject:srcResource(toload)])
-      return false;
+    if ([_preloaded containsObject:srcResource(toload)])
+      nb++;
   }
-  return true;
+  return nb;
 }
 
 - (void)onImageLoad:(NSString *)loaded
 {
   if (!_preloadingDone) {
     [_preloaded addObject:loaded];
-    if ([self allPreloaded]) {
+    int count = [self countPreloaded];
+    int total = (int) [_imagesToPreload count];
+    double progress = ((double) count) / ((double) total);
+    [self dispatchOnProgress:progress withLoaded:count withTotal:total];
+    if (count == total) {
+      [self dispatchOnLoad];
       _preloadingDone = true;
       [self requestSyncData];
     }
diff --git a/RNGL/GLCanvasManager.m b/RNGL/GLCanvasManager.m
index cf99b4db987bd0b93416ee94b903ab932145d872..d3c934c2e496703c4785c28ea1d865661494c4b8 100644
--- a/RNGL/GLCanvasManager.m
+++ b/RNGL/GLCanvasManager.m
@@ -23,6 +23,8 @@ RCT_EXPORT_VIEW_PROPERTY(opaque, BOOL);
 RCT_EXPORT_VIEW_PROPERTY(data, GLData);
 RCT_EXPORT_VIEW_PROPERTY(renderId, NSNumber);
 RCT_EXPORT_VIEW_PROPERTY(imagesToPreload, NSArray);
+RCT_EXPORT_VIEW_PROPERTY(onLoad, BOOL);
+RCT_EXPORT_VIEW_PROPERTY(onProgress, BOOL);
 
 - (UIView *)view
 {