1

I am trying to use ngReact instead of ngRepeat to improve performance when I modify my $watched array of objects.

The react component works, and the html is displayed correctly. For each marker contained in the controller, I want to create a <button>, with the marker.title as text.

However it's super slow, much slower than ngRepeat, and the console shows an infinite list of the same error:

[Error] Deprecated attempt to access property 'nodeType' on a non-Node object.
    n (angular.min.js, line 7)
    sa (angular.min.js, line 11)
    $digest (angular.min.js, line 129)
    $apply (angular.min.js, line 132)
    l (angular.min.js, line 85)
    O (angular.min.js, line 89)
    (funzione anonima) (angular.min.js, line 90)
    m (angular.min.js, line 89)

Here it is my React component (at the end of my post, there is the JSfiddle link)

HTML

<!-- ctrl is the controller, having a list of markers -->
<poi-list list="ctrl.getMarkers()" ctrl="ctrl"/>

JS

.value( "PoiList", React.createClass( {

  propTypes : {

    list: React.PropTypes.object.isRequired,
    ctrl: React.PropTypes.object.isRequired
  },

  render: function() 
   {
    var ctrl = this.props.ctrl; // directive's Controller

    var markers = this.props.list.map( function( marker, i ) 
        {//for each marker, create a button
         return React.DOM.button(  {
                                    className:'btn btn-default',
                                    onClick: function(){ctrl.doSomething(marker);},
                                    onMouseOver: function(){ctrl.doSomethingElse(marker);},                               
                                   }, marker.title
                                 ) ; 
        } );
    return React.DOM.div(null, markers);
    }


}))

.directive( 'poiList', function( reactDirective ) {
  return reactDirective( 'PoiList' );
} );

this is a (new version) JSFiddle of my problem. A brief description: - there is a MapBox directive, to show the map on the page. After 1s, it loads 3 markers on the map, to simulate an ajax request. - for each marker loaded, it will pushed in a list of the PanelController which is responsible to show the names of the markers on a left panel. The names are shown by a React component, using ng-React. It works, however there is that error that slows down the whole system. console error

Any idea of what can be the problem? thank you

DeLac
  • 1,068
  • 13
  • 43
  • your fiddle doesn't work. It is throwing module errors. I recommend replacing `angular.min.js` with a full `angular.js`, correcting the other module load errors, then reposting a more descriptive error. – Claies Aug 24 '15 at 15:57
  • I also see the error `Refused to execute script from 'https://raw.githubusercontent.com/davidchang/ngReact/master/ngReact.min.js' because its MIME type ('text/plain') is not executable, and strict MIME type checking is enabled.` when trying to run your fiddle – Matthew Herbst Aug 24 '15 at 17:55
  • I don't see the errors you say.... this (https://jsfiddle.net/a2b9jc93/) is a jsfiddle version with an empty list, and here I don't have any error. In the original jsfiddle, the console is full of that error I mentioned so I can't see anything else. Anyway the map correctly shows the markers' names. – DeLac Aug 24 '15 at 18:10
  • Why anyone would want to use both Angular AND React in one project is beyond me. Is there some reason I'm not aware of other than technical debt? – Mike Driver Aug 24 '15 at 18:26
  • I have an Angular based system. Just one directive uses ng-repeat with a huge list.... React should improve its performance so...why not? I like angular so, if I can use react just where I need, I am happy with that :) – DeLac Aug 24 '15 at 20:47
  • @DeLac I just checked the fiddles you have posted again, and they are still exhibiting the same `Failed to instantiate module myApp` error. – Claies Aug 24 '15 at 22:45
  • what about now? https://jsfiddle.net/xor74q1m/ I moved the external .js links into the html code, changed their order and used a not minified version of Angular. To me, it works as well as the previous versions. Thank you for the suggestions – DeLac Aug 25 '15 at 10:48
  • @Claies here https://jsfiddle.net/9ot6kj57/ I wrote the ng-react.js library inside my code rather than link it, since there is not CDN repo and this can make problems with jsfiddle. If this work without errors, I'll update the original JSfillde of my question. – DeLac Aug 25 '15 at 15:27
  • I'm still not able to reproduce the issue you are describing, but am continually seeing other issues. With the latest fiddle, if I copy the `map.featureLayer.setGeoJSON()` list from the original fiddle, I get a series of `TypeError: Illegal invocation at isArrayLike`, along with `10 $digest() iterations reached. Aborting!`. This second message, in particular, tells me that you have a watch function which is not impotent, and the result of the watch is changing the value that triggered the watch. Still seems like you have some work to do with the application logic here. – Claies Aug 25 '15 at 18:06
  • When I do `map.featureLayer.setGeoJSON( [ {marker1}, {marker2} ] )`, I pass an array of markers. For each marker of them, it will be executed `ctrl.pushMarker(marker);` that in turn calls `list.push(marker)`, just one time for each marker. The ng-react component iterates on that `list`. I do `ctrl.digest();` to force the update of the list since its loaded by a timeout event, and not by a user interaction. The logic seems right to me.... maybe I can delay the digest, to be sure that the list is full loaded, like this https://jsfiddle.net/rfqu2p7t/ – DeLac Aug 25 '15 at 18:33

1 Answers1

0

Thanks to the comments to my question, I figured out that the real problem is not the deprecated error shown by the Safari console, but it's a problem about the recursive $digest cycle. Using Chrome, the correct error is shown. However I have not yet fixed the issue, so I posted a new question here . Thank you

Community
  • 1
  • 1
DeLac
  • 1,068
  • 13
  • 43