Загрузка текстур "useTexture" react-three/drei
Здравствуйте.
Никак не могу понять в чём разница между функцией "useTexture" из "react-three/drei", и стандартного "TextureLoader" из "Three". Пробовал их обоих в деле, но "TextureLoader" по какой-то причине не может сразу вернуть данные в параметре data. В то же время "useTexture" сразу выдаёт все данные корректно, хотя тоже работает на основе "TextureLoader". К примеру если попробовать вот этот код: const usetex = useTexture(url) const texload = new THREE.TextureLoader().load(url) console.log(usetex.source.data); // Тут всё будет в порядке и вернётся текстура console.log(texload.source.data); // А тут вернёт null Подскажите пожалуйста, в чём между ними разница? |
Не "сразу".
Загрузка текстур - асинхронная операция. Она начинается сейчас - заканчивается когда-нибудь потом. const usetex = useTexture(url) - запускает загрузку при первом обращении и дальше использует механизмы react для сохранения и обновления состояния по мере загрузки. const texload = new THREE.TextureLoader().load(url) - при каждом обновлении компонента заново запускает загрузку текстуры, но никаким не дожидается результата. |
Цитата:
|
Зайти на сайт Three.js и почитать документацию в которой написано как надо использовать TextureLoader.
Тыкнуть тут вверху в Учебник и почитать как работать с асинхронностью. |
Цитата:
|
Raadsert,
Короткий ответ: да. Классический ответ: вынести функцию отдельно, и передавать её в коллбэк, чтоб не было лесенки. Современный ответ: использовать async await чтобы скрыть за ними сложность и получить "плоский" код. useTexture использует механизмы React-фреймворка. Она не "останавливает" код и ничего не ждёт. Она после того как асинхронная загрузка выполнится внутри себя заставляет компонент отрисоваться повторно, при этом возвращая результат. Условно: 1ый рендер компонента: const texture = useTexture(url); // texture === null; 2ый рендер компонента триггернутый из useTexture после загрузки: const texture = useTexture(url); // texture === текстура; 3ий и далее рендер компонента триггернутый разными причинами: const texture = useTexture(url); // texture === текстура; Так работает React. |
Цитата:
|
Raadsert, дополнил ответ. Магии не существует. Синхронный код не может быть асинхронным.
|
Цитата:
|
Raadsert, нет, повторную отрисовку реакт-компонента. Сам почитай про реакт и как он работает, мне неохота тут переписывать документацию реакта или устраивать лекцию.
|
Цитата:
Кроме того, не могу понять логику того как у "useTexture" получается делать то, чего не получается у "TextureLoader", он ведь основывается на нём. Хотелось бы разобраться, каким способом реакту, получается устранить недостатки "TextureLoader", но к сожалению не нашёл ни одной статьи на эту тему. |
А ты ищи статьи по реакту в целом, а не по твоей херне.
В рекате функция useTexture вызывается стопицот раз. В первый она нихрена не возвращает, только запускает внутри где-то загрузку и ставит флаг что загрузка пошла. Пока загрузка идёт - она всё ещё нихрена не возвращает. Когда загрузка закончилась, она снова внутри ставит флаг что загрузка завершена и следующий вызов уже возвращает загруженное. Вот тебе утрированный код как это работает: <script> const условныеПотрохаРеактКомпонета = {}; function условныйРеакт(компонент) { // вместо статического интервала тут реакции на события, но не суть setInterval(() => { document.body.innerHTML = компонент(); }, 1000); } function загрузитьАсинхронно(url, колбэк){ setTimeout(() => колбэк('текстура, ёба'), 5000); } function useTexture(url) { if(условныеПотрохаРеактКомпонета.загружено) return условныеПотрохаРеактКомпонета.текстура; if(условныеПотрохаРеактКомпонета.грузится) return 'нихуя, жди'; условныеПотрохаРеактКомпонета.грузится = true; загрузитьАсинхронно(url, (result) => { условныеПотрохаРеактКомпонета.грузится = false; условныеПотрохаРеактКомпонета.загружено = true; условныеПотрохаРеактКомпонета.текстура = result; }); return 'нихуя, жди' } let i = 0; function нарисоватьХуйнюНаЭкранеКомпонент() { const texture = useTexture('http://хуй.пизда'); return '<b>' + texture + '</b> (нарисовано раз ' + ++i + ')'; } условныйРеакт(нарисоватьХуйнюНаЭкранеКомпонент); </script> Если даже это не поможет, то медицина тут бессильна. |
Цитата:
Получается, реакт создаёт некие события, которые повторно проходятся по функции и обновляют переменные? А почему тогда при первом обходе кода, приложением, оно не выдаёт ошибки на пустые или неподходящие переменные? |
Raadsert, надо смотреть конкретный код, очевидно. Может там есть какие-то проверки на такой случай, может по умолчанию оно возвращает не пустоту, а какую-нить однопиксельную пустую текстуру...
|
Цитата:
|
Цитата:
|
Raadsert, для хранения состояния там используется useState, который возвращает значение и функцию для изменения этого значения.
const [value, setValue] = useState(...);и тут всё просто: функция setValue помимо того что устанавливает новое значение, заодно ещё и триггерит обновление компонента после этого.(опять же - условно, там всё чуть сложней для оптимизации, но суть именно такая) Это setValue всегда одно для каждого useState(генерится один раз при первом обращении) и может быть вызвано когда угодно откуда угодно. |
Цитата:
|
Цитата:
|
Часовой пояс GMT +3, время: 16:20. |