2015-08-26 4 views
0

Я пытался решить это самостоятельно часами и сейчас поднимаю руку, чтобы узнать, есть ли у кого-нибудь идеи.Переменные, объявленные внутри цикла, сохраняют прежние значения

Проблема

Делаю динамический врезку фильтр, который перебирает в groups реквизита и возвращает Link с опорой запроса для обновления маршрутизатора. Отображается флажок и помечен на основе того, исключен ли этот идентификатор группы.

Кодекс

render: function() { 
 
    return (
 
    <ul> 
 
    {this.props.query.filter == 'connections' ? 
 
    // the array of groups to build the filter for 
 
    this.props.groups.map(function (group) { 
 
    // this array would start with the currently excluded ids, and end with the new list of ids 
 
    var new_ids = this.context.router.getCurrentQuery().exclude || []; 
 
    var index = new_ids.indexOf(group.id.toString()); 
 
    console.log('my id: ' + group.id); 
 
    console.log('starting: ' + new_ids); 
 
    // again, the array is excluded ids, so if it's not in the array it should be checked 
 
    var selected = index == -1; 
 
    if (selected) { 
 
     // if this link is clicked, add the id to the excludes 
 
     new_ids.push(group.id); 
 
    } 
 
    else { 
 
     // if this linked is clicked, remove the id from the excludes 
 
     new_ids.splice(index, 1); 
 
    } 
 
    console.log('ending: '+new_ids); 
 
    // return the preloaded link 
 
    return <Link key={group.name} 
 
        to="feed" 
 
        query={{filter: 'connections', exclude: new_ids}}> 
 
       <small>{group.name}</small> 
 
      </Link>; 
 
     }, this) : null } 
 
    </ul> 
 
);

Это работает, когда я использую input type="checkbox" и обработчик событий с this.transitionTo, но я хотел бы использовать Link компоненты для обработки запросов вместо обработчик события.

Результаты

страница работает отлично для первого щелчка (query.exclude == undefined), но после того, что new_ids мутирует с каждой итерации. Это консольный вывод ...

id: 11 
starting: 
new ids: 11 
id: 6 
starting: 
new ids: 6 
id: 21 
starting: 
new ids: 21 

После нажатия одной (скажем, первая группа - ID 11, он портит) ...

id: 11 
starting: 11 
new ids: // this is correct, it removes 11 from the list 
id: 6 
starting: // this should be 11, instead its inheriting the prior value 
new ids: 6 // this should be 11, 6 
id: 21 
starting: 6 // this should be 11, instead its inheriting the prior value 
new ids: 6,21 // this should be 11, 21 

Я попытался сделать это итерация a for ... loop вместо .map(), но это не помогло. Я также перенес исходные исключенные_иды из итерации, но опять же результат.

Опять же, все это должно сделать, это генерировать значения query.exclude опор для навигации, основанной на результатах, нажав на ссылку.

Любые идеи относительно того, что может быть повышено, будут оценены. Спасибо.

+0

Что вы хотите сделать с распределенным массивом? 'Array.prototype.map' возвращает массив, но вы ничего не делаете с ним. – MinusFour

+0

Я обновил код ... он просто строит список ссылок для функции рендеринга. –

+0

Сохраняет ли закрытие прежние значения? – zer00ne

ответ

0

Моя проблема была из-за не вполне понимая назначение переменной в массиве. Я думал, что копирую массив, но я просто ссылался на него. Итак, я фактически исказил первоначальную ценность.

Я исправил это, изменив переменную new_ids, чтобы получить результаты Array.prototype.slice().

slice не меняется. Он возвращает неглубокую копию элементов из исходного массива. - MDN

Так что моя новая линия выглядит следующим образом:

var new_ids = (this.context.router.getCurrentQuery().exclude || []).slice(); 
1

Вот как вы можете избежать мутации массива exclude.

render: function() { 
 
    return (
 
    <ul> 
 
    {this.props.query.filter == 'connections' ? 
 
    // the array of groups to build the filter for 
 
    this.props.groups.map(function (group) { 
 
    // this array would start with the currently excluded ids, and end with the new list of ids 
 
    var new_ids = this.context.router.getCurrentQuery().exclude || []; 
 
    console.log('my id: ' + group.id); 
 
    console.log('starting: ' + new_ids); 
 
     
 
    var found = false; 
 
    new_ids = new_ids.filter(function(exclude){ 
 
     if(exclude != group.id.toString()){ 
 
      return true; 
 
     } else { 
 
      found = true; 
 
      return false; 
 
     } 
 
    }); 
 

 
    if(!found) { 
 
     new_ids.push(group.id); 
 
    } 
 
    //new_ids now has a copy of the exclude array with the values excluded. 
 

 
    console.log('ending: '+new_ids); 
 
    // return the preloaded link 
 
    return <Link key={group.name} 
 
        to="feed" 
 
        query={{filter: 'connections', exclude: new_ids}}> 
 
       <small>{group.name}</small> 
 
      </Link>; 
 
     }, this) : null } 
 
    </ul> 
 
);

Array.prototype.filter в основном проходит через массив и проверить каждый элемент. Если возвращаемое значение равно true, оно добавляет к новому массиву else, итерацию элемента отбрасывают.

Настоящий скрипт, который не реагирует, работает аналогичным образом.

var group = [1,2,3,4,5,6,7,8,9,10,11]; 
 
var excluded = [11]; 
 
var results = document.getElementById('results'); 
 

 
group.forEach(function(group){ 
 
    var new_ids = excluded; 
 
    results.innerHTML += 'my id: ' + group + '\n'; 
 
    results.innerHTML += 'starting: ' + new_ids + '\n'; 
 
    
 
    var found = false; 
 
    new_ids = new_ids.filter(function(exclude){ 
 
     if(exclude != group){ 
 
      return true; 
 
     } else { 
 
      found = true; 
 
      return false; 
 
     } 
 
    }); 
 
     
 
    if(!found){ 
 
     new_ids.push(group); 
 
    } 
 
    results.innerHTML += 'ending: ' + new_ids + '\n'; 
 
});
<pre id="results"></pre>

+0

По какой-то причине это не правильно создало новый массив, когда я нахожусь в Chrome .. но копирование массива с '.slice()' делает. –

+0

Возможно, это вызов '.toString()'. – MinusFour

+0

Он работает, но, похоже, для обработки требуется немного больше времени, чем использование '.slice()'. Вы определенно указали мне в правильном направлении! –

Смежные вопросы