#javascript #reactjs #create-react-app
#javascript #reactjs #create-react-app
Вопрос:
Я новичок в React и пытаюсь создать игру с картами, в которой websocket возвращает массив названий карт, а во внешнем интерфейсе я генерирую правильные изображения карт из локального каталога изображений. Имена карточек, возвращаемые из websocket, соответствуют имени файла изображения, например, «map» соответствует изображению «map.jpg «. Я пытаюсь отобразить массив и создать тег изображения для каждого имени карты в массиве. Я читал, что лучший способ — использовать require()
, и поэтому я попытался сделать что-то вроде
//inside component
let cardImgs;
...
socket.on(RECEIVED_STARTING_HAND, (hand) => {
cardImgs = hand.map(cardName => <img src= {require(`../../card_images/${cardName}.jpg`)}/>
})
…Чтобы позже в моем компоненте я мог сделать что-то вроде этого:
return (
<div>
<h1>My hand</h1>
{cardImgs}
</div>
...
)
Однако, cardImgs
не выполняется рендеринг. В моей return
инструкции моего компонента я протестировал рендеринг изображения напрямую, и это сработало, например
const map = "map"
return (
<div>
<h1>My hand</h1>
{cardImgs}
</div>
...
//this one renders!!!
<img src={require(`../../card_images/${map}.jpg`)} />
)
Я создал свое приложение react с помощью Create-React-App и прочитал кое-что, в чем говорилось, что я должен перенастроить свой webpack.config.js
файл, но затем я также прочитал кое-что, в чем говорилось, что я не должен трогать его без крайней необходимости. Я не уверен, почему require()
это работает, когда я делаю это в return
инструкции моего компонента, но это не работает, когда задан массив тегов изображений. Я что-то упускаю или у вас есть какие-либо предложения по улучшению способов динамической загрузки изображений в React? Спасибо!
Комментарии:
1. используйте import, который, несомненно, поможет.
2. У меня есть ~ 40 изображений, и я хочу динамически загружать изображения на основе предоставленных карточек. Наличие 40 инструкций импорта просто приводит к беспорядку. Я надеялся, что этому найдется альтернатива.
3. require не работает в react, единственный другой способ, который я могу придумать, — разместить изображение в облаке, таком как AWS или Azure, а затем вы сможете загружать его динамически.
4. Есть: разместите свои статические ресурсы как статические ресурсы вместо того, чтобы пытаться объединить их. Особенно, если есть данные, которые не будут меняться каждые полдня, такие как изображения, CSS сайта или webfonts. А затем загрузите их с помощью
<img>
компонента, потому что для этого и предназначенimg
элемент.5. @Mike ‘Pomax’ Kamermans Не могли бы вы, пожалуйста, показать пример? Вы имеете в виду разместить их как статические ресурсы в облаке?
Ответ №1:
Я рекомендую просто обработать элемент состояния hand
в вашем рендере. При обновлении значения запустится рендеринг и будут созданы ваши изображения.
{hand.map((cardName, index) => (
<img key={cardName} src={`pathtoserver/card_images/${cardName}.jpg`}/>
))}
Комментарии:
1. Вы случайно не знаете, какой путь к серверу, если вы используете create-react-app? Я пытаюсь перемещаться, начиная с разных папок, но не могу найти правильный путь.
2. При создании приложения react у вас не будет доступа к серверу, поскольку это всего лишь упрощенная настройка сервера для разработки, если вы имеете в виду свой внутренний сервер, который зависит от вас.
3. у react нет доступа по умолчанию к данному серверу. статические ресурсы в create-react-app сохраняются в
/public
, если это вам поможет. это может помочь вам, если все ваши изображения карточек хранятся в приложении react, а не на сервере4. @Mike’Pomax’Camermans хороший момент, не предполагающий ничего в приведенном выше примере, но обновит его
5. отлично, комментарий отозван. Люди думают, что они могут просто использовать позицию массива для
key
атрибута так часто , что это одна из основных причин, по которой приложения React работают плохо, когда они работают плохо.
Ответ №2:
если вы хотите отобразить изображение из локальной папки, вы можете импортировать нужные вам изображения с помощью синтаксиса import и после этого использовать его в своем теге img
import card1 from '../you/path/to/image.png';
import card2 from '../you/path/to/image.png';
import card3 from '../you/path/to/image.png';
const cards = {
nameToCard1: card1,
nameToCard2: card2,
nameToCard3: card3,
}
в вашем методе сокета:
socket.on(RECEIVED_STARTING_HAND, (hand) => {
cardImgs = hand.map(cardName => cards[cardName] />
})
и в вашем методе рендеринга:
return (
<div>
<h1>My hand</h1>
<ul>
{cardImgs.map((img) => <li><img key={img} src={img} /></li>)}
</ul>
</div>
)
надеюсь, это поможет вам, хорошего дня.
Комментарии:
1. не забудьте добавить
key
атрибуты при использованииmap
(и помните, что они должны быть реальными, уникальными значениями для компонента, а не «положением в массиве»)2. О, вы правы. Я продолжу редактировать сообщение, чтобы получить правильный пример
3. И затем вы сделали именно то, что я напомнил вам не делать. Используйте уникальный идентификатор , то есть что-то, что всегда идентифицирует этот элемент : если у меня есть
['a','b']
и['b','a']
, изменил ли я оба элемента или просто поменял их местами? Для этогоkey
и используется. У вас уже есть идеальный уникальный идентификатор, он прямо здесь, вы уже назначаете егоsrc
, используйте его как ключ DOM diffing . Пожалуйста, прочитайте reactjs.org/docs/lists-and-keys.html#keys и поймите, почему вам нужно присвоить этому атрибуту правильное значение, потому что использовать позиции списка — значит подставлять себе ногу.4. Спасибо за информацию, я приношу извинения и исправляю проблему, используя src изображения в качестве уникального идентификатора
5. Но почему
key={`${img}`}
? Просто скажитеkey={img}
? И вы используете функцию со стрелкой, так что:<div><h1>..</h1><ul>{cardImgs.map(url => <li><img key={url} src={url} /></li>)}</ul></div>
и готово?