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. Будет обновляться с комментариями выше относительно того, почему это не решение