Home > database >  Get error when added async and await inside for loop
Get error when added async and await inside for loop

Time:12-30

Why when I added await inside for-loop, it will throw me error? How should I fix it?

export default async function DetailsViewer({
}) {

  const galleryList = [];
  const metadata = []

  const [data, setData] = useState()


  useEffect(() => {

    const getNFTDetails = async () => {
      fetch("http://localhost:4000/getDetails").then(response => {
        return response.json()
      })
        .then(posts => {
          setData(posts)

        })
        .then((err) => {
          console.log(err);
        })
    }
    getNFTDetails()
  }, []);

  for (const a in data) {
    metadata[a] = await fetchIPFSJSON(data[a].uri);
    if (metadata[a].image) {
      metadata[a].image = makeGatewayURL(metadata[a].image);
    }
    galleryList.push(
      <Card
        style={{ width: 200 }}
        key={data[a].name}
        title={
          <div>
            {data[a].name}{" "}
            <a
              target="_blank"
              rel="noreferrer"
            >
              {/* <LinkOutlined /> */}
            </a>
          </div>
        }
      >
        <img src={data[a].image} style={{ maxWidth: 130 }} />
      </Card>,
    );
  }
  return (

    <div style={{ maxWidth: 820, margin: "auto", marginTop: 32, paddingBottom: 256 }}>

      <StackGrid columnWidth={200} gutterWidth={16} gutterHeight={16}>
        {galleryList}
      </StackGrid>
    </div>
  )
}

Error

Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead. in NFTViewer (at App.jsx:271) in Route (at App.jsx:270) in Switch (at App.jsx:261) in Router (created by BrowserRouter) in BrowserRouter (at App.jsx:242) in div (at App.jsx:239) in App (at src/index.jsx:25) in ThemeSwitcherProvider (at src/index.jsx:24) in ApolloProvider (at src/index.jsx:2

CodePudding user response:

You should declare a separate async function that triggers when data changes.
Also, galleryList should be a state so the page will re-render when it populates:

export default function DetailsViewer({}) {
  const metadata = {};

  const [galleryList, setGalleryList] = useState([]);
  const [data, setData] = useState([]);

  useEffect(() => {
    const getNFTDetails = async () => {
      try {
        const response = await fetch('http://localhost:4000/getDetails');
        const posts = await response.json();
        setData(posts);
      } catch (err) {
        console.log(err);
      }
    };
    getNFTDetails();
  }, []);

  useEffect(() => {
    handleData();
  }, [data]);

  const handleData = async () => {
    const list = [];
    for (const a in data) {
      metadata[a] = await fetchIPFSJSON(data[a].uri);
      if (metadata[a].image) {
        metadata[a].image = makeGatewayURL(metadata[a].image);
      }
      list.push(
        <Card
          style={{ width: 200 }}
          key={data[a].name}
          title={
            <div>
              {data[a].name}{' '}
              <a target='_blank' rel='noreferrer'>
                {/* <LinkOutlined /> */}
              </a>
            </div>
          }
        >
          <img src={data[a].image} style={{ maxWidth: 130 }} />
        </Card>
      );
    }
    setGalleryList(list);
  };

  return (
    <div
      style={{
        maxWidth: 820,
        margin: 'auto',
        marginTop: 32,
        paddingBottom: 256,
      }}
    >
      <StackGrid columnWidth={200} gutterWidth={16} gutterHeight={16}>
        {galleryList}
      </StackGrid>
    </div>
  );
}

CodePudding user response:

useEffect(() => {

    const createGalleryList= async () => {
      for (const a in data) {
    metadata[a] = await fetchIPFSJSON(data[a].uri);
    if (metadata[a].image) {
      metadata[a].image = makeGatewayURL(metadata[a].image);
    }
    galleryList.push(
      <Card
        style={{ width: 200 }}
        key={data[a].name}
        title={
          <div>
            {data[a].name}{" "}
            <a
              target="_blank"
              rel="noreferrer"
            >
              {/* <LinkOutlined /> */}
            </a>
          </div>
        }
      >
        <img src={data[a].image} style={{ maxWidth: 130 }} />
      </Card>,
    );
  }
    }
    createGalleryList()
  }, [data]);

Create new useEffect and call the galleryList creation variable whenever data is changed. Don't use async in default functions and await in open. use galleryList as state var, at it renders when changed.

  • Related