HASEEB Ahmed
HASEEB Ahmed

Reputation: 109

How do I destructure a promise returned by axios?

Below is the code to fetch some data

    useEffect(async (id) => {
//    const data = await redditFetch(id);
async function redditFetch(id){
    try {
        const {data:{data}} = await axios.get(`https://www.reddit.com/search.json?q=${id}&limit=50`);
        const {children} = data;
        return children.map(data=> data.data);
    } catch (error) {
        console.log(error);
    }
}
const data = redditFetch(id);
setData(data)
},[setData])

console.log(Data);

And this is the promise returned:

Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Array(50)

What I want is the Array inside the PromiseResult.

I've also tried another away using async await like this which returns a proper array.

const PostPage = () => {
    const {id} = useParams();
    const [Data, setData] = useState([])
    
    useEffect(async (id) => {
    //    const data = await redditFetch(id);
    async function redditFetch(id){
        try {
            const {data:{data}} = await axios.get(`https://www.reddit.com/search.json?q=${id}&limit=50`);
            const {children} = data;
            return children.map(data=> data.data);
        } catch (error) {
            console.log(error);
        }
    }
    const data = await redditFetch(id);
    setData(data)
    },[setData])

    console.log(Data);

But with this comes a bloody warning that I can't get rid of:

index.js:1 Warning: An effect function must not return anything besides a function, which is used for clean-up.

It looks like you wrote useEffect(async () => ...) or returned a Promise. Instead, write the async function inside your effect and call it immediately:

useEffect(() => { async function fetchData() { // You can await here const response = await MyAPI.getData(someId); // ... } fetchData(); }, [someId]); // Or [] if effect doesn't need props or state

So, my dear coders, tell me what to do???

Upvotes: 0

Views: 1656

Answers (2)

I did a sample demo with the post code:

CODESANDBOX: https://codesandbox.io/s/flamboyant-nobel-p87mt9?file=/src/App.js:257-265

  • In your code const data = redditFetch(id); the async functions will return a Promise. You have to use await, but React will warn you to not transform the useEffect callback in async function
  • You can remove the API function of your useEffect.
  • Don't put the setDate in your useEffect dependency array. In this case, you can leave this empty to run just one time. Also, don't put the date because will re-render in an infinite loop. If you need some conditional just remove the dependency array and put some conditional to run setDate.

I had to mock the id in the query parameter to be possible to work with API

CODE:

import axios from "axios";
import { useEffect, useState } from "react";
import "./styles.css";

async function redditFetch() {
  try {
    const {
      data: { data }
    } = await axios.get(`https://www.reddit.com/search.json?q=01&limit=50`);
    const { children } = data;
    return children.map((data) => data.data);
  } catch (error) {
    console.log(error);
  }
}

export default function App() {
  const [data, setData] = useState([]);

  const Data = data.map((redditContent) => {
    return (
      <div key={redditContent.name}>
        <h2>{redditContent.title}</h2>
        <hr />
      </div>
    );
  });

  useEffect(() => {
    (async function () {
      const redditResponse = await redditFetch();
      console.log(redditResponse);
      setData(redditResponse);
    })();
  }, []);

  return <div className="App">{Data}</div>;
}

ALTERNATIVE: CLEANER APPROACH (No anonymous function)

If you don't like of anonymous function approach, you can use this one:

  async function updateRedditPosts() {
    const redditResponse = await redditFetch();
    console.log(redditResponse);
    setData(redditResponse);
  }

  useEffect(() => {
    updateRedditPosts();
  }, []);

Upvotes: 0

hmamun
hmamun

Reputation: 154

Anything return from useEffect supposed to be clean up while component unmount. Better you may invoke setData function there instead of return.

On the other hand, you may use immediate invoke function (IIF) then you do not need to resolve the promise that return from redditFetch function.

Upvotes: -1

Related Questions