如何在 reactjs 中获取承诺值?

How to get the promise value in reactjs?

我正在尝试在单个页面上渲染存储在 firebase 上的多个图像。

这是获取图片的函数url:

async getTokenImage(fileName) {
    const ref = firebase.storage().ref('token/' + fileName);
    const url = await ref.getDownloadURL();
    console.log('in here')
    return url
}

这是函数调用:

<div
     class="card-img-top" 
     style={{
        backgroundColor: '#'+token.color, 
        backgroundImage: 'url('+this.getTokenImage(token.fileName).then((value) => {return value})+')'
     }}></div>

控制台记录“值”给出了所需的图像url

但是返回“值”什么也没有。
为了测试,我这样做了:

let image = this.getTokenImage(token.fileName).then((result) => {return result})
console.log(image)

结果是:

那么如何在初始函数调用中获取图像 url?

祖父组件的一部分:

<MintedTokens
    account={this.state.account} 
    contract={this.state.contract} 
    tokens={this.state.tokens} />

父组件:

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组件(需要渲染多张图片的地方):

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;

我无法很好地测试它,但您可以尝试以下操作:

添加:

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})`

所有代码:

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;

如果你的 React 版本 > 16.8,我建议你开始使用 Stateless Components and Hooks。并阅读 React 的生命周期和渲染方法 here: