【问题标题】:How to get the promise value in reactjs?reactjs中如何获取promise值?
【发布时间】:2021-06-03 09:28:23
【问题描述】:

我正在尝试在单个页面上渲染存储在 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;

子组件(需要渲染多个图像的地方):

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;

【问题讨论】:

  • .then((thing) =&gt; { return thing; }) 没有做任何有用的事情,结果仍然是价值的promise
  • 您需要进行渲染以在承诺响应后更新您的 DOM。你在使用无状态组件吗? @jonrsharpe
  • @rigojr 是的,它是一个无状态组件,需要的数据正在通过 props 传递。
  • @RahulMehta 你能把父组件和它的子组件贴出来吗,this 关键字只能用在类组件上,我只想通读一遍,让你知道你可以在哪里渲染。
  • @rigojr 在这种特殊情况下,实际上是祖父、父亲和孩子。我已经添加了他们三个的代码。

标签: reactjs promise es6-promise


【解决方案1】:

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

添加:

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,我建议您开始使用无状态组件和 Hooks。并阅读 React 的生命周期和渲染方法here

【讨论】:

  • 谢谢!这是完美的作品。我确实想过在这种情况下使用状态,但我担心如果它必须加载数十张图像,那么它可能会影响效率?
  • 很好!!请记住,组件第一次挂载时,这些图像将没有 url,因为 promise 会响应并且需要一些时间,在这种情况下将进行一些渲染,因为我们使用的是 Promise.all()。记住,阅读生命周期,非常重要!
猜你喜欢
  • 2021-12-28
  • 1970-01-01
  • 2018-05-16
  • 1970-01-01
  • 2022-01-18
  • 2020-04-30
  • 2023-03-07
  • 1970-01-01
  • 2022-12-06
相关资源
最近更新 更多