admin管理员组

文章数量:1352840

export const FETCH_DB_BEGIN = 'FETCH_DB_BEGIN'
export const FETCH_DB_SUCCESS = 'FETCH_DB_SUCCESS'
export const FETCH_DB_FAILURE = 'FETCH_DB_FAILURE'

export const fetchDatabase = () => {
    return dispatch => {
        const profile_url = 'localhost:5000/profiles'
        const release_url = 'localhost:5000/releases'
        const emp_url = 'localhost:5000/users'
        let promises = []

        let options = {
            headers: header,
            method: 'get',
            mode: 'cors',
            body: null,
        }
        dispatch(fetchDbBegin());

        // run the script async. change state when it's done.
        let profile_promise = new Promise((resolve, reject) => {
            fetch(profile_url, options)
                .then(res => res.json())
                .then(resText => {
                    // Use Dispatch Here?
                })
        }).catch(err => {
            console.log(err)
        })
        promises.push(profile_promise)

        // run the script async. change state when it's done.
        let release_promise = new Promise((resolve, reject) => {
            fetch(release_url, options)
                .then(res => res.json())
                .then(resText => {
                })
        }).catch(err => {
            console.log(err)
        })
        promises.push(release_promise)

        // run the script async. change state when it's done.
        let emp_promise = new Promise((resolve, reject) => {
            fetch(emp_url, options)
                .then(res => res.json())
                .then(resText => {

                })
        }).catch(err => {
            console.log(err)
        })
        promises.push(emp_promise)

        Promise.all(promises).then(values => {
            console.log(values)
        })
    }
}

export const fetchDbBegin = () => ({
    type: FETCH_DB_BEGIN
});

export const fetchDbSuccess = (data) => ({
    type: FETCH_DB_SUCCESS,
    payload: { data }
});

export const fetchDbFailure = (err) => ({
    type: FETCH_DB_FAILURE,
    payload: { err }
});

I am in a process of refactoring a React class ponent to use Redux. It initially had all API calls inside the ponentDidMount and it was so messy.

I am using redux-thunk to move this out from the class ponent.

The fetchDatabase in my databaseAction.js does everything that ponentDidMount did in the class ponent.

Normally if it was a single API call, I would have just dispatched the fetchDbSuccess as the API call was done successfully. However, using Promise.All which takes three async API calls, I am not sure whether I should

  1. create a separate action for each API call (fetchProfileSuccess, fetchReleaseSuccess, and fetchUserSuccess) and dispatch each one of them at the end of each Promise (the place where I put //Use Dispatch Here? in the code.

OR

  1. Just dispatch single fetchDbSuccess when the Promise.all gets resolved.

If I choose to do 2, am I supposed to update all three states in my reducer?

Thanks

export const FETCH_DB_BEGIN = 'FETCH_DB_BEGIN'
export const FETCH_DB_SUCCESS = 'FETCH_DB_SUCCESS'
export const FETCH_DB_FAILURE = 'FETCH_DB_FAILURE'

export const fetchDatabase = () => {
    return dispatch => {
        const profile_url = 'localhost:5000/profiles'
        const release_url = 'localhost:5000/releases'
        const emp_url = 'localhost:5000/users'
        let promises = []

        let options = {
            headers: header,
            method: 'get',
            mode: 'cors',
            body: null,
        }
        dispatch(fetchDbBegin());

        // run the script async. change state when it's done.
        let profile_promise = new Promise((resolve, reject) => {
            fetch(profile_url, options)
                .then(res => res.json())
                .then(resText => {
                    // Use Dispatch Here?
                })
        }).catch(err => {
            console.log(err)
        })
        promises.push(profile_promise)

        // run the script async. change state when it's done.
        let release_promise = new Promise((resolve, reject) => {
            fetch(release_url, options)
                .then(res => res.json())
                .then(resText => {
                })
        }).catch(err => {
            console.log(err)
        })
        promises.push(release_promise)

        // run the script async. change state when it's done.
        let emp_promise = new Promise((resolve, reject) => {
            fetch(emp_url, options)
                .then(res => res.json())
                .then(resText => {

                })
        }).catch(err => {
            console.log(err)
        })
        promises.push(emp_promise)

        Promise.all(promises).then(values => {
            console.log(values)
        })
    }
}

export const fetchDbBegin = () => ({
    type: FETCH_DB_BEGIN
});

export const fetchDbSuccess = (data) => ({
    type: FETCH_DB_SUCCESS,
    payload: { data }
});

export const fetchDbFailure = (err) => ({
    type: FETCH_DB_FAILURE,
    payload: { err }
});

I am in a process of refactoring a React class ponent to use Redux. It initially had all API calls inside the ponentDidMount and it was so messy.

I am using redux-thunk to move this out from the class ponent.

The fetchDatabase in my databaseAction.js does everything that ponentDidMount did in the class ponent.

Normally if it was a single API call, I would have just dispatched the fetchDbSuccess as the API call was done successfully. However, using Promise.All which takes three async API calls, I am not sure whether I should

  1. create a separate action for each API call (fetchProfileSuccess, fetchReleaseSuccess, and fetchUserSuccess) and dispatch each one of them at the end of each Promise (the place where I put //Use Dispatch Here? in the code.

OR

  1. Just dispatch single fetchDbSuccess when the Promise.all gets resolved.

If I choose to do 2, am I supposed to update all three states in my reducer?

Thanks

Share Improve this question edited Oct 10, 2019 at 23:59 Dawn17 asked Oct 10, 2019 at 23:53 Dawn17Dawn17 8,29717 gold badges65 silver badges132 bronze badges 5
  • How many actions you dispatch depends on which state updates you expect to take place. If your UI doesn't care about all three fetches, only if the top-level fetch finished, you could just do the one success action. If you're wanting to show something specific for each one, you'd do the separate actions. – Jacob Commented Oct 11, 2019 at 0:01
  • @Jacob Thanks. So are both approaches correct? – Dawn17 Commented Oct 11, 2019 at 0:02
  • Yep. By the way, your sample code isn't doing the Promises correctly since the new Promise callbacks aren't calling resolve or reject (and the new Promise wrappers aren't necessary since fetch() already returns Promises) – Jacob Commented Oct 11, 2019 at 0:04
  • @Jacob How should I fix them? Initially I had this.setState after .then(resText => ... in the Class Component so that it updates each data once the fetch was successfully done and it seemed to do what I intended. – Dawn17 Commented Oct 11, 2019 at 0:05
  • I will post in an answer so there's more space. – Jacob Commented Oct 11, 2019 at 0:06
Add a ment  | 

1 Answer 1

Reset to default 7

You should only dispatch and update state if you have code that cares about said state updates. For example, if you're just wanting to show a single spinner then have the spinner go away when fully pleted, your user doesn't necessarily care about each atomic operation, so you don't need it reflected in state. If you have a UI that does show each, then you would want those extra dispatches.

By the way, your Promises look a bit overplicated. If you decide you don't need those extra state changes, you can simplify to this:

export const FETCH_DB_BEGIN = 'FETCH_DB_BEGIN'
export const FETCH_DB_SUCCESS = 'FETCH_DB_SUCCESS'
export const FETCH_DB_FAILURE = 'FETCH_DB_FAILURE'

export const fetchDatabase = () => {
    return dispatch => {
        dispatch(fetchDbBegin());

        const urls = [
            'http://localhost:5000/profiles',
            'http://localhost:5000/releases',
            'http://localhost:5000/users'
        ];

        const options = {
            headers: header,
            method: 'get',
            mode: 'cors',
            body: null,
        }

        const fetchJson = url => fetch(url, options).then(res => res.json());

        Promise.all(urls.map(fetchJson))
            .then(([profile, release, employee]) => {
                dispatch(fetchDbSuccess({ profile, release, employee }));
            })
            .catch(err => {
                dispatch(fetchDbFailure(err));
            });
    }
}

export const fetchDbBegin = () => ({
    type: FETCH_DB_BEGIN
});

export const fetchDbSuccess = (data) => ({
    type: FETCH_DB_SUCCESS,
    payload: { data }
});

export const fetchDbFailure = (err) => ({
    type: FETCH_DB_FAILURE,
    payload: { err }
});

本文标签: javascriptWhat is the bettercorrect way of using Promiseall with ReactReduxThunkStack Overflow