React Native - moduł wymagania obrazu przy użyciu nazw dynamicznych


87

Obecnie tworzę aplikację testową przy użyciu React Native. Jak dotąd moduł obrazu działał dobrze.

Na przykład, gdybym miał nazwany obraz avatar, poniższy fragment kodu działa dobrze.

<Image source={require('image!avatar')} />

Ale jeśli zmienię go na dynamiczny ciąg, otrzymam

<Image source={require('image!' + 'avatar')} />

Wyskakuje mi błąd:

Wymaganie nieznanego modułu „image! Avatar”. Jeśli jesteś pewien, że moduł tam jest, spróbuj ponownie uruchomić program pakujący.

Oczywiście jest to wymyślony przykład, ale dynamiczne nazwy obrazów są ważne. Czy React Native nie obsługuje dynamicznych nazw obrazów?

Reaguj na natywny błąd z dynamiczną nazwą obrazu


1
Napotkałem podobny problem z Vue, odpowiedź jest tutaj stackoverflow.com/questions/40491506/…
Alonad

Odpowiedzi:


73

Jest to omówione w dokumentacji w sekcji „ Zasoby statyczne ”:

Jedynym dozwolonym sposobem odniesienia się do obrazu w pakiecie jest dosłowne zapisanie w źródle wymagania („obraz! Nazwa-zasobu”).

// GOOD
<Image source={require('image!my-icon')} />

// BAD
var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive';
<Image source={require('image!' + icon)} />

// GOOD
var icon = this.props.active ? require('image!my-icon-active') : require('image!my-icon-inactive');
<Image source={icon} />

Musisz jednak pamiętać, aby dodać swoje obrazy do pakietu xcassets w swojej aplikacji w Xcode, chociaż wydaje się, że z twojego komentarza już to zrobiłeś.

http://facebook.github.io/react-native/docs/image.html#adding-static-resources-to-your-app-using-images-xcassets


1
gdzie powinienem dodać obrazy, używam React Native dla Androida, w folderze do rysowania?
coderzzz18

2
Powyższy link jest nieprawidłowy, artykuł jest teraz na facebook.github.io/react-native/docs/images.html
app_sciences

51
cześć, jak to zrobić, jeśli mam setki obrazów, których potrzebujesz?
chanjianyi

1
@chanjianyi Jestem w tej samej sytuacji :-(
pon.

1
„Wymagaj” nie działa na urządzeniach IOS. Jakieś pomysły dlaczego?
Arthur Medeiros

59

To zadziałało dla mnie:

Zrobiłem niestandardowy komponent obrazu, który przyjmuje wartość logiczną, aby sprawdzić, czy obraz pochodzi z sieci lub jest przekazywany z folderu lokalnego.

// In index.ios.js after importing the component
<CustomImage fromWeb={false} imageName={require('./images/logo.png')}/>

// In CustomImage.js which is my image component
<Image style={styles.image} source={this.props.imageName} />

Jeśli widzisz kod, zamiast jednego z nich:

// NOTE: Neither of these will work
source={require('../images/'+imageName)} 
var imageName = require('../images/'+imageName)

Całość wysyłam require('./images/logo.png')jako rekwizyt. To działa!


5
Ta odpowiedź zasługuje na więcej uznania. Absolutnie działa, gdy zadeklarujesz instrukcję require i przekażesz ją jako właściwość. Dziękuję bardzo za proste wyjaśnienie, chciałbym tylko, aby inni byli tak jasni.
dazziola

1
Rekwizyt działa cuda. Należy to zaznaczyć w oficjalnych dokumentach.
dasmikko

1
class CustomImage extends Component { constructor(props) { super(props); } render() { return ( <Image source={this.props.imageName} resizeMode="contain" style={{ height: 24, width: 24 }} /> ); } } <CustomImage fromWeb={false} imageName={require(`../../images/phone-${item.status}.png`)} />
Pablo

1
W komponencie nadrzędnym mam <CustomImage fromWeb={false} imageName={require(../../assets/icons/${el.img}.png, )} /> a to w komponencie podrzędnymclass CustomImage extends Component { constructor(props) { super(props); } render() { return ( <Image source={this.props.imageName} resizeMode="contain" style={{ height: 24, width: 24 }} /> ); } }
Walter Monecke

2
Czysty geniusz, właśnie tego szukałem :)
Sumit Sahoo

54

WAŻNE, JEŚLI MASZ ZNANE OBRAZY (ADRESY URL):

Sposób, w jaki włamałem się do tego problemu:

Utworzyłem plik z obiektem, który przechował obraz i nazwę obrazu:

const images = {
  dog: {
    imgName: 'Dog', 
    uri: require('path/to/local/image')
  },
  cat: {
    imgName: 'Cat on a Boat', 
    uri: require('path/to/local/image')
  }
}

export { images };

Następnie zaimportowałem obiekt do komponentu, w którym chcę go użyć i po prostu wykonuję renderowanie warunkowe w następujący sposób:

import { images } from 'relative/path';

if (cond === 'cat') {
  let imgSource = images.cat.uri;
}

<Image source={imgSource} />

Wiem, że nie jest to najbardziej efektywny sposób, ale zdecydowanie jest to obejście.

Mam nadzieję, że to pomoże!


3
Zgrabne rozwiązanie do obsługi znanego zestawu obrazów
Tedy Kanjirathinkal

1
@TedyKanjirathinkal Cieszę się, że pomogło!
Walter Monecke

1
Dziękuję, to się przyda
Truca

@WalterMonecke: Otrzymuję wartość całkowitą, jeśli to zrobimy
sabir

30

Jeśli szukasz sposobu na utworzenie listy, na przykład przez zapętlenie tablicy JSON obrazów i opisów, to zadziała.

  1. Utwórz plik (do przechowywania naszej bazy danych JSON), np. ProfilesDB.js:

const Profiles=[
	  {
	  "id" : "1",
	  "name" : "Peter Parker",
	  "src" : require('../images/user1.png'),
	  "age":"70",
	},
	{
	"id" : "2",
	"name" : "Barack Obama",
	"src" : require('../images/user2.png'),
	"age":"19",
	},
	{
	"id" : "3",
	"name" : "Hilary Clinton",
	"src" : require('../images/user3.png'),
	"age":"50",
	}
]
export default Profiles;

  1. Następnie zaimportuj dane do naszego komponentu i przejrzyj listę za pomocą FlatList:

import Profiles from './ProfilesDB.js';

<FlatList
  data={Profiles}
  keyExtractor={(item, index) => item.id}
  renderItem={({item}) => (
    <View>
      <Image source={item.src} />
      <Text>{item.name}</Text>
    </View>
  )}
/>

Powodzenia!


3
Dzięki, to zadziałało dla mnie po tak wielu frustracjach!
cherucole

12

Jak mówi React Native Documentation , wszystkie źródła obrazów muszą zostać załadowane przed skompilowaniem pakietu

Innym sposobem wykorzystania dynamicznych obrazów jest użycie instrukcji switch. Powiedzmy, że chcesz wyświetlić inny awatar dla innej postaci, możesz zrobić coś takiego:

class App extends Component {
  state = { avatar: "" }

  get avatarImage() {
    switch (this.state.avatar) {
      case "spiderman":
        return require('./spiderman.png');
      case "batman":
        return require('./batman.png');
      case "hulk":
        return require('./hulk.png');
      default:
        return require('./no-image.png');
    }
  }

  render() {
    return <Image source={this.avatarImage} />
  }
}

Sprawdź przekąskę: https://snack.expo.io/@abranhe/dynamic-images

Pamiętaj też, że jeśli Twój obraz jest online, nie masz żadnych problemów, możesz:

let superhero = "spiderman";

<Image source={{ uri: `https://some-website.online/${superhero}.png` }} />

8

Najpierw utwórz plik z wymaganym obrazem - obrazy natywne React muszą być ładowane w ten sposób.

aktywa / index.js

export const friendsandfoe = require('./friends-and-foe.png'); 
export const lifeanddeath = require('./life-and-death.png'); 
export const homeandgarden = require('./home-and-garden.png');

Teraz zaimportuj wszystkie swoje zasoby

App.js

import * as All  from '../../assets';

Możesz teraz użyć swojego obrazu jako wartości interpolowanej, gdzie wartość imageValue (pochodząca z zaplecza) jest taka sama, jak nazwany plik lokalny, tj. „Homeandgarden”:

<Image style={styles.image} source={All[`${imageValue}`]}></Image>

Niezłe rozwiązanie, bardzo mi pomogło! Tks.
Fryla- Cristian Marucci

Bez obaw! Nie mogłem znaleźć tutaj dobrego rozwiązania, więc wymyśliłem własne :) Cieszę się, że pomogłem.
HannahCarney

6

Ważna część tutaj: nie możemy łączyć nazwy obrazu wewnątrz wymagania, takiego jak [require ('item' + vairable + '. Png')]

Krok 1: Tworzymy plik ImageCollection.js z następującą kolekcją właściwości obrazu

ImageCollection.js
================================
export default images={
    "1": require("./item1.png"),
    "2": require("./item2.png"),
    "3": require("./item3.png"),
    "4": require("./item4.png"),
    "5": require("./item5.png")
}

Krok 2: Zaimportuj obraz do aplikacji i zmodyfikuj go w razie potrzeby

class ListRepoApp extends Component {

    renderItem = ({item }) => (
        <View style={styles.item}>
            <Text>Item number :{item}</Text>
            <Image source={Images[item]}/>
        </View>
    );

    render () {
        const data = ["1","2","3","4","5"]
        return (
            <FlatList data={data} renderItem={this.renderItem}/>
        )
    }
}

export default ListRepoApp;

Jeśli chcesz uzyskać szczegółowe wyjaśnienie, możesz kliknąć poniższe łącze Odwiedź https://www.thelearninguy.com/react-native-require-image-using-dynamic-names

Dzięki uprzejmości: https://www.thelearninguy.com


6
import React, { Component } from 'react';
import { Image } from 'react-native';

class Images extends Component {
  constructor(props) {
    super(props);
    this.state = {
           images: {
                './assets/RetailerLogo/1.jpg': require('../../../assets/RetailerLogo/1.jpg'),
                './assets/RetailerLogo/2.jpg': require('../../../assets/RetailerLogo/2.jpg'),
                './assets/RetailerLogo/3.jpg': require('../../../assets/RetailerLogo/3.jpg')
            }
    }
  }

  render() {
    const {  images } = this.state 
    return (
      <View>
        <Image
                            resizeMode="contain"
                            source={ images['assets/RetailerLogo/1.jpg'] }
                            style={styles.itemImg}
                        />
     </View>
  )}
}


4

Aby dynamiczny obraz za pomocą require

this.state={
       //defualt image
       newimage: require('../../../src/assets/group/kids_room3.png'),
       randomImages=[
         {
            image:require('../../../src/assets/group/kids_room1.png')
          },
         {
            image:require('../../../src/assets/group/kids_room2.png')
          }
        ,
         {
            image:require('../../../src/assets/group/kids_room3.png')
          }
        
        
        ]

}

po naciśnięciu przycisku - (wybieram losowy numer obrazu między 0-2))

let setImage=>(){
//set new dynamic image 
this.setState({newimage:this.state.randomImages[Math.floor(Math.random() * 3)];
})
}

widok

<Image
        style={{  width: 30, height: 30 ,zIndex: 500 }}
        
        source={this.state.newimage}
      />


2
 <StyledInput text="NAME" imgUri={require('../assets/userIcon.png')} ></StyledInput> 

<Image
            source={this.props.imgUri}
            style={{
              height: 30,
              width: 30,
              resizeMode: 'contain',
            }}
          />   

w moim przypadku bardzo się starałem, ale w końcu działa obraz nazwy komponentu StyledInput wewnątrz StyledInput jeśli nadal nie rozumiesz, daj mi znać


2

Powiedz, jeśli masz aplikację, która ma podobną funkcjonalność jak moja. Gdzie Twoja aplikacja jest w większości offline i chcesz renderować obrazy jeden po drugim. Poniżej znajduje się podejście, które działało dla mnie w React Native w wersji 0.60.

  1. Najpierw utwórz folder o nazwie Zasoby / Obrazy i umieść tam wszystkie swoje obrazy.
  2. Teraz utwórz plik o nazwie Index.js (w Resources / Images), który jest odpowiedzialny za indeksowanie wszystkich obrazów w folderze Reources / Images .

const Images = {'image1': require ('./ 1.png'), 'image2': require ('./ 2.png'), 'image3': require ('./ 3.png')}

  1. Teraz utwórz składnik o nazwie ImageView w wybranym folderze. Można stworzyć element funkcjonalny, klasowy lub stały. Użyłem komponentu Const. Ten plik jest odpowiedzialny za zwrócenie obrazu w zależności od indeksu.
import React from 'react';
import { Image, Dimensions } from 'react-native';
import Images from './Index';
const ImageView = ({ index }) => {
    return (
        <Image
            source={Images['image' + index]}
        />
    )
}
export default ImageView;
  1. Teraz z komponentu, w którym chcesz dynamicznie renderować obrazy statyczne, po prostu użyj komponentu ImageView i przekaż indeks.

    <ImageView index = {this.qno + 1} />


-2

Powinieneś użyć do tego przedmiotu.

Na przykład, powiedzmy, że wysłałem żądanie AJAX do API i zwraca link do obrazu, który zapiszę jako imageLink:

source={{uri: this.state.imageLink}}


3
w przypadku dynamicznych linków do ścieżek obrazu to nie działa: var img = "../img/icons/"+img_name+"_selected.png"; <br/> <Image source={{uri: img}} resizeMode={'contain'} />
Robert Tomas G IV

4
hack do tego, jeśli znasz wszystkie warianty img_name, pójdzie w ten sposób:var images = { 'first': require('../first.png'), 'second': require('../second.png') } <Image source={{uri:images[img_name]}} resizeMode={'contain'} />
Gabriel Lupu

2
Ostrzegamy, że za sugestię @GabrielLupu: w ten sposób przydzielasz wszystkie obrazy w pamięci. Zależy to od liczby obrazów i ich rozmiarów, jednak prawdopodobnie wystąpią błędy braku pamięci.
Lashae
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.