3
\$\begingroup\$

update1:

- I need to make two different api calls. - from the result of first api call I am getting id in the variable firstAPIid, https://reqres.in/api/users?page=2 - I need to pass this id firstAPIid to the second api call.

  • can you review my code.
  • I did multiple api calls through promise.
  • right way is through promise or async or call back.
  • providing my code snippet and sandbox below.

https://codesandbox.io/s/redux-async-actions-xjdo7

<FetchButton
          onFetchClick={() => {
            store.dispatch(dispatchFunc => {
              dispatchFunc({ type: "FETCH_DATA_START" });
              axios
                .get("https://reqres.in/api/users?page=2")
                // axios.get('https://jsonplaceholder.typicode.com/posts')
                .then(response => {
                  console.log("response.data.data---->", response.data.data);
                  console.log(
                    "response.data.data[0].id---->",
                    response.data.data[0].id
                  );
                  //First of all we'll create the number of requestes base on the previous Response
                  const promises = response.data.data.reduce(
                    (previousValue, { id }) => {
                      previousValue.push(
                        axios.get(
                          `https://jsonplaceholder.typicode.com/comments?postId=${id}`
                        )
                      );
                      console.log(
                        " promises previousValue---->",
                        previousValue
                      );

                      return previousValue;
                    },
                    []
                  );

                  console.log("promises---->", promises);

                  //We use the built in function to fetch the data
                  axios.all(promises).then(responses => {
                    //Here you have all responses processed
                    const emailsMapped = responses.reduce(
                      (previousValue, { data }) => {
                        const emails = data.map(({ email }) => email);
                        previousValue.push(...emails);
                        return previousValue;
                      },
                      []
                    );
                    //You send the emails you want
                    dispatchFunc({
                      type: "RECEIVED_DATA",
                      payload: emailsMapped
                    });
                    console.log(emailsMapped);
                  });
                })
                .catch(err => {
                  dispatchFunc({ type: "FETCH_DATA_ERROR", payload: err });
                });
            });
          }}
        />
\$\endgroup\$
  • \$\begingroup\$ Could you tell us what your code is about? \$\endgroup\$ – dfhwze Jul 22 at 19:38
  • \$\begingroup\$ hey updated the question \$\endgroup\$ – zi zi Jul 22 at 19:42
  • \$\begingroup\$ This code look like the code from medium.com/@rk./… Are you the author of the code in the your question? \$\endgroup\$ – Blindman67 Jul 22 at 20:46
1
\$\begingroup\$

First of all, putting all your code in the props of your JSX is making it unreadable. Extract this into a function, and have your JSX reference that instead.

Next, for debugging, I would recommend using breakpoints to debug code. console.log() is fine for a quick peek, but it introduces a lot of noise in the code.

Also, when you expand a logged object in the console, you see the object's structure at the time of expanding, not at the time of logging. The object's contents may have already changed between the time it was logged and when you expanded it. If you're not aware of this quirk, you'll easily think your code is broken.

For promises, you're really just mapping. Use array.map() instead of array.reduce(). For emailsMapped, which is also just a mapping operation, since you're adding multiple items, use array.flatMap() for that.

Lastly, you can modify your code so that you can chain the promises instead of nesting them. You can return the promise of axios.all() to chain it to your axios.get().

store.dispatch(dispatchFunc => {
  dispatchFunc({ type: "FETCH_DATA_START" });
  axios
    .get("https://reqres.in/api/users?page=2")
    .then(response => {
      const promises = response.data.data.map(({ id }) => {
        return axios.get(`https://.../comments?postId=${id}`)
      })

      return axios.all(promises)
    })
    .then(responses => {
      const emailsMapped = responses.flatMap(({ data }) => {
        return data.map(({ email }) => email)
      })

      dispatchFunc({
        type: "RECEIVED_DATA",
        payload: emailsMapped
      })
    })
    .catch(err => {
      dispatchFunc({
        type: "FETCH_DATA_ERROR",
        payload: err
      })
    })
})

Now that we've established a more linear flow via chaining, we can take this a bit further and convert it to an async function so that we can use await:

// Note the async here
store.dispatch(async dispatchFunc => {
  dispatchFunc({ type: "FETCH_DATA_START" });

  try {
    // Note the various await before each asynchronous function call

    const response = await axios.get("https://reqres.in/api/users?page=2")

    const promises = response.data.data.map(({ id }) => {
      return axios.get(`https://.../comments?postId=${id}`)
    })

    const responses = await axios.all(promises)

    const emailsMapped = responses.flatMap(({ data }) => {
      return data.map(({ email }) => email)
    })

    dispatchFunc({
      type: "RECEIVED_DATA",
      payload: emailsMapped
    })
  } catch (err) {
    dispatchFunc({
      type: "FETCH_DATA_ERROR",
      payload: err
    })
  }
})
\$\endgroup\$
  • \$\begingroup\$ hey for performance promise or async is good...can you let me know why you used flat map \$\endgroup\$ – zi zi Jul 24 at 17:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.