Значение закрытия изменяется без сброса - PullRequest
0 голосов
/ 21 марта 2019

ПРИМЕЧАНИЕ, ЧТО ЭТО РЕШЕНО

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

Я создаю замыкание в mergeProps для использования в качестве действия удаления. Он получает selectedItems из состояния или данных с сервера, если форма еще не затронута. Пользователь может удалять или добавлять элементы из списка, но когда я добавляю 2, а затем удаляю верхний элемент, происходит что-то странное.

Согласно журналам, замыкание не воссоздается, но длина selectedItems равна 1 (он отсутствует без повторного создания замыкания).

Это происходит как в Chrome, так и в Firefox, код:

const mergeProps = (
  stateProps,
  dispatchProps,
  ownProps,
) => {
  //make a copy of selected items to be used for the closure of
  //  onDelete in case but is caused by other code mutating it
  const copy = JSON.parse(
    JSON.stringify(stateProps.selectedItems || []),
  );
  console.log(
    new Date().getTime(),
    'creating closure, length is:',
    copy.length,
  );
  return {
    ...stateProps,
    ...ownProps,
    onDelete: ({ id: entityId, entityType }) =>
      console.log(
        'in the closure, length is now:',
        copy.length,
      ) ||
      onDeleteDataFilter(
        entityId,
        entityType,
        ownProps.onChange,
        copy,
      ),
  };
};

Когда я добавляю 2 элемента и удаляю верхний элемент, вывод консоли будет таким:

1553159774414 creating closure, length is: 2 
in the closure, length is now: 1
1553159785005 creating closure, length is: 0

Мне кажется невозможным, что copy можно изменить без повторного вызова close, но это то, что я получаю.

selectedItems были обработаны таблицей начальной реакции, и, похоже, это имеет свое собственное состояние, поэтому каждая строка получает свою onDelete функцию.

Изменение переменных замыкания может произойти только тогда, когда вы изменяете переменную, и в этом случае я просто записал неправильную вещь, думая, что массив был изменен, но вместо этого каждая строка в таблице начальной загрузки получила свою собственную функцию замыкания (см. Ответ).

1 Ответ

0 голосов
/ 21 марта 2019

Фактическая проблема была вызвана тем, что выбранные элементы были переданы в BootstrapTable, и почему-то каждая строка в этой таблице получает свою собственную функцию закрытия .Поэтому я добавляю один элемент с именем A, который имеет действие удаления с selectedItems из [A].Я добавляю B он имеет функцию закрытия с selectedItems из [A,B].Удаление B будет работать, но удаление A не удастся, потому что у него нет правильной функции закрытия.

При добавлении счетчика на закрытие я мог видеть, что номер счетчика был неправильным для элементов, которые не былипоследний элемент:

let counter = 1;
const mergeProps = (
  stateProps,
  dispatchProps,
  ownProps,
) => {
  const copy = JSON.parse(
    JSON.stringify(stateProps.selectedItems|| []),
  );
  const copyCounter = counter;
  counter++;
  console.log('creating closure for counter:', copyCounter);
  return {
    ...stateProps,
    ...ownProps,
    onDelete: ({ id: entityId, entityType }) =>
      console.log(
        'in the closure, counter is:',
        copyCounter,
      ) ||
      onDeleteDataFilter(
        entityId,
        entityType,
        ownProps.onChange,
        copy,
      ),
  };
};

Решение

Для принудительной реакции таблицы начальной загрузки и использования одинаковых функций onDelete для каждой строки я добавил уникальный ключ key={new Date().getTime()}, это запустит конструктор и смонтируетпоэтому onDelete в подпорках будет одинаковым для каждой строки.

...