Reputation: 67
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;
Upvotes: 1
Views: 840
Reputation: 202605
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!!).
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>
);
}
}
Upvotes: 1