在渲染方法中渲染“异步”函数返回值(反应)

时间:2021-04-05 16:03:02

标签: javascript reactjs function render

我正在尝试从我的 React 应用程序中的 async 函数呈现一个简单的返回值,但是每次我尝试我的整个应用程序时都不会呈现。不调用该函数我的应用程序呈现良好。此外,如果我在我的函数中 console.log 我的返回值(结果),它会在控制台上返回正确的值,但应用程序中没有任何内容呈现。知道发生了什么吗?

class TitleCards extends Component {
    constructor(props){
        super(props)
        this.totalPortfolio = this.totalPortfolio.bind(this);
        this.getIntradayPrice = this.getIntradayPrice.bind(this);

    }

    async getIntradayPrice(tick) {
        const resp = await fetch(`${IEX.base_url}/stock/${tick}/intraday-prices?chartLast=1&token=${IEX.api_token}`);
        return resp.json();
      }

    async totalPortfolio() {
        const respPromises = this.props.info.map(({ tick }) => this.getIntradayPrice(tick));
        const respArrays = await Promise.all(respPromises);
        console.log(respArrays);
        const result = respArrays.reduce((acc, val, index) => acc + val[0].close * this.props.info[index].amtPurch, 0)
        console.log(result);
        return result;
      }
      
    render(){  
        return(
            <div className="positioning">
                <div className="StockCardTitle">
                    <img src={Folder} className="StockCardTitle-image" /> 
                    {this.totalPortfolio()}
                </div>
            </div>
        )
    }
}

export default TitleCards;

1 个答案:

答案 0 :(得分:1)

问题

React 组件和生命周期是 100% 同步的,尤其是 render 方法。 render 方法也被视为纯函数,这意味着它应该具有零副作用(例如获取数据!!)。

解决方案

您应该重构代码以在 componentDidMountcomponentDidUpdate 之一或两者中获取数据并将结果保存到本地组件状态以进行渲染。

这是一个重构示例。

class TitleCards extends Component {
  constructor(props){
    super(props);

    state = {
      portfolioTotal: '',
    };

    this.totalPortfolio = this.totalPortfolio.bind(this);
    this.getIntradayPrice = this.getIntradayPrice.bind(this);
  }

  async getIntradayPrice(tick) {
    const resp = await fetch(`${IEX.base_url}/stock/${tick}/intraday-prices?chartLast=1&token=${IEX.api_token}`);
    return resp.json();
  }

  async totalPortfolio() {
    const { info } = this.props;
    const respPromises = info.map(({ tick }) => this.getIntradayPrice(tick));
    const respArrays = await Promise.all(respPromises);
    const result = respArrays.reduce((acc, val, index) => acc + val[0].close * info[index].amtPurch, 0)
    return result;
  }

  // When the component mounts, call totalPortfolio
  componentDidMount() {
    this.totalPortfolio()
      .then(portfolioTotal => {
        this.setState({
          portfolioTotal
        });
      })
      .catch(error => {
        // add any required error handling/messaging here
      });
  }

  render() {
    const { portfolioTotal } = this.state;
    return(
      return(
        <div className="positioning">
          <div className="StockCardTitle">
            <img src={Folder} className="StockCardTitle-image" /> 
            {portfolioTotal} // <-- render state value
          </div>
        </div>
    );
  }
}