циклические объекты, недопустимый вызов isArrayLike () и цикл Infinite $ digest, создающий <div> с помощью ngReact

0

[ОБНОВЛЕНО, 24 сентября]

Я пытаюсь использовать ngReact вместо ngRepeat для повышения производительности, когда я изменяю свой массив объектов с просмотром $.

Для каждого объекта (маркера карты), содержащегося в контроллере, я хочу создать <button>, а в качестве текста - marker.title. Для этой цели я создал компонент React, который $ смотрит массив маркеров. Такой список содержит список, по одному для каждого маркера. Я предположил, что компонент будет изменен, только если я изменю список маркеров, а затем список кнопок. Однако, это не так.

[TypeError]: Illegal invocation
  at isArrayLike (angular.js:274)
  at forEach (angular.js:328)
  at copy (angular.js:886)

[Error]: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
http://errors.angularjs.org/1.4.0-rc.0/$rootScope/infdig?p0=10&p1=%5B%5D
    at REGEX_STRING_REGEXP (angular.js:68)
    at Scope.parent.$get.Scope.$digest (angular.js:15340)
    at Scope.parent.$get.Scope.$apply (angular.js:15570)
    at (index):95

Кажется, что список <button> созданный компонентом React, всегда отличается, даже если он сделан теми же объектами.

Теперь странная часть. Собственно, я добавляю маркеры на карту, используя объекты Json. Когда я добавляю объект Json, карта создает объект Marker, а не jsonable, потому что он имеет круговую структуру. Я добавляю этот объект Marker к моему $ watched массиву, чтобы создать относительную <button>... Может быть, это причина illegal isArrayLike()?

Здесь это мой компонент React (в конце моего сообщения есть ссылка JSfiddle)

HTML

    <!-- m_list is an attribute of $rootScope -->
    <poi-list list="m_list" />

JS

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

  propTypes : {

    list: React.PropTypes.object.isRequired
  },

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


}))

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

это JSFiddle моей проблемы. Короткое описание:

  • в $ rootScope есть 2 массива. temp_list используется для временного нажатия всех маркеров по одному. m_list - это $, наблюдаемый компонентом реакции.
  • есть директива MapBox с контроллером. Для каждого добавленного к карте маркера он будет помещен в temp_list.
  • после того, как все маркеры были загружены, и temp_list будет завершен, это клонируется в m_list, так что компонент реакции может быть обновлен.

Спасибо

Теги:
dom
clone
ngreact

1 ответ

0
Лучший ответ

Я нашел решение! Проблема как-то связана с использованием карты. В наблюдаемом массиве я не добавляю маркеры Json, но добавляю маркер объекта, созданный MapBox.

map.featureLayer.setGeoJSON(json_markers_list);  // I pass an array of Json markers
map.featureLayer.on('layeradd', function(e) 
                {
                     var marker = e.layer;        // marker is anymore a json obj
                     ctrl.pushMarker(marker);  // marker now has a cyclic structure
                    });

Маркер объекта, созданный MapBox, имеет циклическую структуру. По этой причине React не может знать, изменился ли старый $ watched массив с момента последней проверки, потому что он не может выполнить isArrayLike() когда структура цикла присутствует. Таким образом, он вызывает ошибку (различается в любом браузере) и считает массив всегда измененным, генерируя бесконечную итерацию $ digest.

Мое решение использует один массив и одну карту. Массив $ смотрел только с информацией, которую мне нужно отображать в кнопке

{'title': 'marker title', 'id':00001}

карта содержит реальные объекты маркера

{'00001' : {markerObj}}

и это рабочий JSFiddle ! Нажмите кнопку, и объект маркера будет выбран.

Этот вопрос и решение - это также плакат на форуме официального проекта ng-react

Ещё вопросы

Сообщество Overcoder
Наверх
Меню