Игнорирует ли React реквизиты, являющиеся буферами массива для обновления элементов, если ключ тот же?

reactjs #react-hooks

#reactjs #реагирующие хуки

Вопрос:

Мне интересно, как React решает повторно отобразить определенные элементы. У меня есть приложение, в котором затем пользователь переключает вкладки, я обновляю <AssetContainer> . Иногда этот контейнер будет содержать asset с тем же document_id , который используется для ключа. Я замечаю, что когда я создаю ресурс, мой эффект запускается, чтобы установить URL-адрес миниатюры в blob fine. Я переключаю вкладки, создаю ресурс с тем же файлом, и он создает еще один новый большой двоичный объект. Затем, когда я переключаюсь обратно на первую вкладку, она НЕ будет повторно отображаться. Несмотря на то, что он передается в новом asset.thumbnail.image , он обрабатывает его как то же самое. Я должен отметить asset.thumbnail.image , что это буфер массива. Заставляет ли это React игнорировать значение при поиске обновлений?

У меня есть такой код:

 <AssetContainer>
{assets.map((asset) => (
      <Asset
        key={asset.document_id}
        thumbnail={asset.thumbnail!.image!}
        thumbnailFormat={asset.thumbnail!.format!}
        hasClaim={!!asset.provenance}
        errors={asset.errors}
        size="80px"
      />
    )
)}
</AssetContainer>
 

Внутри <Asset> у меня есть следующий эффект и код, в <AssetView thumbnailUrl={thumbnailUrl} size={size}></AssetView> котором это определяется как:

 // The effect in Asset
useEffect(() => {
  let blobUrl;
  if (thumbnail) {
    const imgData = Array.isArray(thumbnail)
      ? thumbnail
      : new Uint8Array(Object.values(thumbnail));
    const blob = new Blob([imgData], { type: thumbnailFormat });
    blobUrl = URL.createObjectURL(blob);
    // this is what stops firing every time i switch tabs which should re-render the elements based on new data in the tab
    console.log('setting thumbnail url', blobUrl);
    setThumbnailUrl(blobUrl);
  }
  return () => {
    if (blobUrl) {
      URL.revokeObjectURL(blobUrl);
    }
  };
}, []);

// The AssetView definition for the tag invocation above
const AssetView = styled.div`
  display: inline-flex;
  align-items: flex-end;
  justify-content: flex-end;
  flex-shrink: 0;
  width: ${(props) => props.size};
  height: ${(props) => props.size};
  margin-right: 4px;
  margin-bottom: 4px;
  border-radius: 2px;
  background-color: #434646;
  background-image: ${(props) =>
    props.thumbnailUrl ? `url("${props.thumbnailUrl}")` : 'none'};
  background-size: contain;
  background-position: center;
`;
 

Короткая версия такова: каждый раз, когда я переключаю вкладки, <Asset> рендерится так, как ожидалось. Я вижу console.log огонь каждый раз перед возвратом <AssetView> . Однако useEffect <Asset> ofне запускается, когда обновляется реквизит буфера массива, когда key он такой же, как и раньше. Не уверен, почему.

Обновление почему выполнение [эскиза] в эффекте не является ответом, это не проблема, поскольку все обновляется нормально из-за перемонтирования компонентов более высокого уровня. Если я выполняю это предложение, каждый раз, когда я переключаю вкладки, он повторно запускает эффект использования и генерирует новый URL-адрес большого двоичного объекта, который мне не нужен. Поведение как есть заключается в том, что на вкладке A он будет генерировать Blob-1, а на вкладке B он будет генерировать Blob-2. Когда я возвращаюсь на вкладку A, я хочу Blob-1, но все равно получаю Blob-2.

Я считаю, что проблема в том, что key значение одинаково для обеих вкладок (что я исправлю), но я не уверен, насколько высоко нужно подняться (если возможно), чтобы React игнорировал key . Если бы это было только key то, что вызывало кэширование, оно даже не должно генерировать Blob-2.

Ответ №1:

Не thumbnail должны быть включены в ваш массив зависимостей эффектов?

 useEffect(() => {
    // ...
}, [props.thumbnail]);
 

В противном случае эффект будет выполняться только один раз с пустым массивом

Комментарии:

1. Будет обновляться с комментариями выше относительно того, почему это не решение