I am trying to render multiple images, stored on firebase, on a single page.
This is the function to get the image url:
async getTokenImage(fileName) {
const ref = firebase.storage().ref('token/' + fileName);
const url = await ref.getDownloadURL();
console.log('in here')
return url
}
This is the function call:
<div
class="card-img-top"
style={{
backgroundColor: '#'+token.color,
backgroundImage: 'url('+this.getTokenImage(token.fileName).then((value) => {return value})+')'
}}></div>
console logging the "value" gives the needed image url
but returning the "value" gives nothing.
for the sake of testing, I have done this:
let image = this.getTokenImage(token.fileName).then((result) => {return result})
console.log(image)
So how do I get the image url within the initial function call?
Part of grandfather component:
<MintedTokens
account={this.state.account}
contract={this.state.contract}
tokens={this.state.tokens} />
Father component:
import React from 'react';
import "./minted-tokens.scoped.css";
import MultipleMintedTokens from './multiple-minted-tokens.js';
import SingleMintedTokens from './single-minted-token.js';
class MintedTokens extends React.Component {
render() {
const color = window.location.pathname.split('/')[2]
let display
if(color == undefined) {
display = <MultipleMintedTokens
account={this.props.account}
tokens={this.props.tokens}></MultipleMintedTokens>
} else {
display = <SingleMintedTokens
account={this.props.account}
color={color}
tokens={this.props.tokens}></SingleMintedTokens>
}
return (
<div class="Minted-Token">
{display}
</div>
);
}
}
export default MintedTokens;
Child component (where the multiple images need to be rendered):
import React from 'react';
import ether from '../../assets/ether.svg'
import firebase from "../../firebase.js"
import { Link } from 'react-router-dom';
class MultipleMintedTokens extends React.Component {
async getTokenImage(fileName) {
const ref = firebase.storage().ref('token/' + fileName);
const url = await ref.getDownloadURL();
console.log('in here')
return url
}
render() {
return (
<div class="welcome minted-tokens">
<h1 class="">Minted Tokens</h1>
<div class="row">
{this.props.tokens.map((token, key) => {
let name = '',
description = ''
if(token.to == this.props.account) {
token.name.length >= 17 ? name = token.name.slice(0,17) + '...' : name = token.name
token.description.length >= 28 ? description = token.description.slice(0,29) + '...' : description = token.description
let image = this.getTokenImage(token.fileName).then((result) => {return result})
console.log(image)
return (
<Link to={token.tokenURI} key={key}>
<div class='token-id'>{token.id}</div>
<div class="card card-width">
<div
class="card-img-top"
style={{
backgroundColor: '#'+token.color,
backgroundImage: 'url('+this.getTokenImage(token.fileName).then((value) => {return value})+')'
}}></div>
<h5 class="card-header" style={{
backgroundColor: '#'+token.color,
color: '#'+token.fontColor}}>{name}</h5>
<div class="card-body">
<p class="card-text">{description}</p>
<div class="foot-of-card">
<span class="row price-row">
<img src={ether} alt="ether" class="icon" />
<p class="card-text">{token.price}</p>
</span>
<p class="card-text datetime">{token.dateTime}</p>
</div>
</div>
</div>
</Link>
)
}
})}
</div>
</div>
);
}
}
export default MultipleMintedTokens;
I could not test it well but you can try the following:
Add:
constructor(props) {
super(props);
this.state = {
urlImgs: [],
};
}
...
componentDidMount() {
const { tokens } = this.props;
const promiseArray = tokens.map((token) => getTokenImage(token.fileName));
Promise.all(promiseArray)
.then(valueArray => {
this.setState(prevState => ({
...prevState,
urlImgs: valueArray
}))
})
.catch(err => console.log(err));
}
...
backgroundImage: `url(${urlImgs[key] ?? null})`
All Code:
class MultipleMintedTokens extends React.Component {
constructor(props) {
super(props);
this.state = {
urlImgs: [],
};
}
async getTokenImage(fileName) {
const ref = firebase.storage().ref('token/' + fileName);
const url = await ref.getDownloadURL();
console.log('in here')
return url
}
componentDidMount() {
const { tokens } = this.props;
const promiseArray = tokens.map((token) => getTokenImage(token.fileName));
Promise.all(promiseArray)
.then(valueArray => {
this.setState(prevState => ({
...prevState,
urlImgs: valueArray
}))
})
.catch(err => console.log(err));
}
render() {
const { urlImgs } = this.state;
return (
<div class="welcome minted-tokens">
<h1 class="">Minted Tokens</h1>
<div class="row">
{this.props.tokens.map((token, key) => {
let name = '',
description = ''
if(token.to == this.props.account) {
token.name.length >= 17 ? name = token.name.slice(0,17) + '...' : name = token.name
token.description.length >= 28 ? description = token.description.slice(0,29) + '...' : description = token.description
let image = this.getTokenImage(token.fileName).then((result) => {return result})
console.log(image)
return (
<Link to={token.tokenURI} key={key}>
<div class='token-id'>{token.id}</div>
<div class="card card-width">
<div
class="card-img-top"
style={{
backgroundColor: '#'+token.color,
backgroundImage: `url(${urlImgs[key] ?? null})`
}}></div>
<h5 class="card-header" style={{
backgroundColor: '#'+token.color,
color: '#'+token.fontColor}}>{name}</h5>
<div class="card-body">
<p class="card-text">{description}</p>
<div class="foot-of-card">
<span class="row price-row">
<img src={ether} alt="ether" class="icon" />
<p class="card-text">{token.price}</p>
</span>
<p class="card-text datetime">{token.dateTime}</p>
</div>
</div>
</div>
</Link>
)
}
})}
</div>
</div>
);
}
}
export default MultipleMintedTokens;
if you have React with version > 16.8, I advice you to start using Stateless Components and Hooks. And read about the lifecycle of React and the render method here: