简体   繁体   中英

How to stop React child component from loading before data from fetch call in parent is passed to it

I am making a website that displays apps and their reviews. each app has a page and each page contains the apps' reviews. it would be super easy if the reviews were part of the data returned in each apps API call but the reviews are their own object with their own call. so basically I would like the apps' page to load the reviews. the problem is I keep getting errors because my child component is rendering twice for some reason and the first time it renders without the reviews. it is also loading before the parent component for some reason I'm not understanding. I've confirmed this by printing the props to the console at each step. the order the data is rendered is: props printed from child component (does not include reviews so I get an undefined error when I try to pull any data), the props printed from the child component (complete with reviews) and then the data from the asynchronous componentDidMount() is printed last. I am using an asynchronous componentDidMount() because I was under the impression that putting await this.fetchData() inside componentDidMount() would cause it to wait until the data is fetched. this is not the case. so yeah, if anyone can tell me how to load this once and correctly it would be great. I've been trying all kinds of different things so if something doesn't make sense or add up it's probably from an earlier attempt and I'll clarify in an edit.

here's the code for the parent

import React from 'react';
import Header from '../universal components/Header';
import DetailsAppHeader from '../details page components/DetailsAppHeader';
import FeatsComponents from '../details page components/FeatsComponents';
import SupportComponent from '../details page components/SupportComponent';
import ReviewsComponent from '../details page components/ReviewsComponent';

export default class DetailPageComponent extends React.Component {
    constructor(props){
        super(props);
        
        this.state = {
            // a bunch of stuff relating to the apps
        }

    async componentDidMount() {
        await this.fetchData()
       // this await is basically useless but it's the last thing I tried 
    }

    fetchData(){
        fetch("http://localhost:3001/reviewsForApp/" + this.state.appId)
        .then(response => response.json())
        .then(response => {
            this.setState({reviews: response.data.list})
        })
    }

    render(){
        return(
            <div>
                <div>
                    <div class="col-10 offset-1">
                        <Header />
                        <DetailsAppHeader appDetails={this.state} />
                        <FeatsComponents appDetails={this.state} />
                        <SupportComponent appDetails={this.state} />
                        <ReviewsComponent appDetails={this.state}/>
                    </div>
                </div>
            </div>
        )
    }
}

and the child

import React from 'react';


const ReviewsComponent = (props) => (
     <div>
          {props.appDetails.reviews && <h3>Most Recent Reviews</h3>}
          {console.log(props.appDetails.reviews)}
          // first time returns undefined the second time it returns the correct data
          <p>{props.appDetails.reviews}</p>
          // this fails because the data is not loaded yet
     </div>
   )


export default ReviewsComponent;

Maybe try only rendering child components when the state is populated, for example:

 render(){ return( <div> <div> <div class="col-10 offset-1"> <Header /> {this.state && ( <DetailsAppHeader appDetails={this.state} /> <FeatsComponents appDetails={this.state} /> <SupportComponent appDetails={this.state} /> <ReviewsComponent appDetails={this.state}/> ) } </div> </div> </div> ) }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM