renakre
renakre

Reputation: 8291

Fetching data just after another fetch is complete in react hooks

I have three separate useEffect functions. One is to fetch submission records:

useEffect(() => {
    if (props.loading_submissions != true) {
        props.fetchSubmissionsByReviewRound(reviewRoundId);
    }
}, [reviewRoundId])

Another one is for fetching Students.

useEffect(() => {
    if (props.loading_students != true) {
       props.fetchStudentsByCourse(courseId, reviewRoundId);
    }
}, [reviewRoundId])

I prefer that Students are fetched first, and once they are loaded and saved in redux state, submissions should be fetched. I wonder how I can achieve this. Any help is appreciated.

Below is the mapStateToProps and mapDispatchToProps methods:

const mapStateToProps = (state) => ({
    submissions: state.submissionReducer.submissions,        
    students: state.studentReducer.students,
    loading_students: state.studentReducer.loading,
    loading_submissions: state.submissionReducer.loading,
    error: state.studentReducer.error,

})

const mapDispatchToProps = (dispatch) => {
    return {
        fetchSubmissionsByReviewRound: (reviewRoundId) => dispatch(FetchSubmissionsByReviewRound(reviewRoundId)),            

        fetchStudentsByCourse: (courseId, reviewRoundId) => dispatch(FetchStudentsByCourse(courseId, reviewRoundId)),
    }
}

I am using axios to fetch the data:

export function FetchStudentsByCourse(courseId, reviewRoundId) {
    return dispatch => {

        dispatch(studentsDataOperationBegin());

        axios.get("api/Student/FetchStudentsByCourse", { params: { courseId, reviewRoundId } })
            .then(response => {
                console.log('Students in the course are fetched by course id.');

                const students = new schema.Entity('students');

                const normalizedData = normalize(response.data, [students]);
                dispatch(fetchStudentsSuccess(normalizedData.entities.students))
            })
            .catch(error => { studentsDataOperationFailure(error) });
    }

}


export function FetchSubmissionsByReviewRound(reviewRoundId) {

    return dispatch => {

        dispatch(submissionDataOperationBegin());

        axios.get('api/Submission/FetchSubmissionsByReviewRound', { params: { reviewRoundId } })
            .then(response => {
                console.log('Submissions are fetched.');

                const submissions = new schema.Entity('submissions');

                const normalizedData = normalize(response.data, [submissions]);
                dispatch(fetchSubmissionsByReviewRoundSuccess(normalizedData.entities.submissions))
            })
            .catch(error => { submissionDataOperationFailure(error) });
    }
}

Upvotes: 0

Views: 1565

Answers (1)

technicallynick
technicallynick

Reputation: 1592

If you're wanting one of them to be dependent upon the other, then I would join them under one useEffect() method and make promise functions out of them. Once done, async/await will be your friend.

However, if you're wanting the data from the Students call to be loaded to the user, then the browser go fetch the other, then I would use a 2nd setState to be monitored for the 2nd call that is modified by the first. Such as this:

const [studentDataReceived, setStudentDataReceived] = useState(false);

useEffect(() => {
    if (props.loading_students != true) {
       props.fetchStudentsByCourse(courseId, reviewRoundId);
    }
    setStudentDataReceived(true)
}, [reviewRoundId])

useEffect(() => {
  if(studentDataReceived){
    if (props.loading_submissions != true) {
        props.fetchSubmissionsByReviewRound(reviewRoundId);
    }
  }
}, [studentDataReceived])

Upvotes: 2

Related Questions