1

I'm trying to render a simple return value from an async function in my react app however every time I try to my entire app will not render at all. Without calling the function my app renders fine. Also if I console.log my return value (result) in my function it returns the correct value on the console but nothing in the app renders. Any ideas what's going on?

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;
2
  • 1
    React components and lifecycle are 100% synchronous, especially the render method. The render method is also considered a pure function, meaning it should have zero side effects, like fetching data. What is this.portfolio in the above snippet? Can you provide a more complete code example so we may see what portfolio function is and what is calling getIntradayPrice and totalPortfolio? Commented Apr 5, 2021 at 16:49
  • So i just added the complete component code. Props are passed in from another component but they are simple arrays. The main problem is rendering a asynch function value which I don't know how to do. Also I had an error in the original code snippet (portfolio function was meant to be totalPortfolio) it has been corrected Commented Apr 5, 2021 at 18:17

1 Answer 1

1

Issue

React components and lifecycle are 100% synchronous, especially the render method. The render method is also considered a pure function, meaning it should have zero side effects (like fetching data!!).

Solution

You should refactor your code to fetch data in one or both of componentDidMount and componentDidUpdate and save the result to local component state for rendering.

Here's an example refactorization.

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>
    );
  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.