Isaac Covarrubias
Isaac Covarrubias

Reputation: 15

Create Button from each item in array React

I am working with Unsplash API and I am trying to get the images to download. I can get them to download, however it downloads every single photo instead of just the one I want when I use a for loop. If I remove the saveAs part outside of the loop it only downloads the final image in the array instead of the others no matter what button I click. Here is my code:

import React, { useState, useEffect } from 'react';
import { Heading } from './components/Heading';
import { Loader } from './components/Loader';
import { UnsplashImage } from './components/UnsplashImage';
import InfiniteScroll from 'react-infinite-scroll-component';
import { saveAs } from 'file-saver';


import axios from 'axios';
import styled from 'styled-components';
import { createGlobalStyle } from 'styled-components';
import SearchPhotos from './components/searchPhotos';
import Heart from './components/Heart';
import { FileUpload } from './components/Upload';

const GlobalStyle = createGlobalStyle`
  *{
    margin: 0px;
    padding: 0px;
    box-sizing: border-box;
  }

  body{
    font-family: sans-serif;
  }
`;

const WrapperImg = styled.section`
  max-width: 70rem;
  margin: 4rem auto;
  display: grid;
  grid-gap: 1em;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
`;

const H1 = styled.h1`
  max-width: 70rem;
  margin: 4rem auto;
`;

const Div = styled.div`
  display: flex;
  flex-direction: column;
  margin-bottom: 2rem;
  height: auto;
  width: 100%;
  position: relative;
`;


function App() {
  const [images, setImages] = useState([]);

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

  const fetchImages = () => {
    const apiURL = "https://api.unsplash.com";
    const apiKey = "MY_KEY_";
    axios
      .get(`${apiURL}/photos/random?client_id=${apiKey}&count=1`)
      .then(res => setImages([...images, ...res.data]))
  }

  const imgURL = images.map((download) => {
    //console.log(download.urls.full)
    return download.urls.full;
  });

  const Download = () => {
    const downloadImage = () => {
      for (var i = 0; i < imgURL.length; i++) {
        var red = imgURL[i];
        //saveAs(red, 'image.jpg');
        console.log(red);
      } 
      //saveAs(red, 'image.jpg');

    }
    return <button onClick={downloadImage}>Download</button>
  }

  return (
    <div className="App">
      <Heading />
      <GlobalStyle />
      <SearchPhotos />
      <InfiniteScroll
        dataLength={images.length}
        next={fetchImages}
        hasMore={true}
        loader={<Loader />}
      >
        <H1>Main Feed:</H1>
        <WrapperImg>
          <FileUpload />
          {images.map(image =>
          (<>
            <Div>
              <Heart />
              <UnsplashImage url={image.urls.thumb} key={image.id} />
              <p className="like"> Amount of Likes ❤️ {image.likes}</p>
              <Download />
            </Div>
          </>))}
        </WrapperImg>
      </InfiniteScroll>
    </div>
  );
}

export default App;

Upvotes: 1

Views: 2235

Answers (3)

Hr meheraj
Hr meheraj

Reputation: 1

You have this question - firstly understand this What is the happening


You can open it in codepen vanilla Javascript or you can skip this. - enter link description here

const root = document.querySelector("#root");

const arr = [1,2,3,4,5];
arr.map(each => {
  const newButton = document.createElement("button");
  newButton.innerHTML = each;
  newButton.addEventListener("click", () => {
    console.log(each);
  })
  root.appendChild(newButton);
})

Now Come to your code :

 <WrapperImg>
      <FileUpload />
      {images.map(image =>
      (<>
        <Div>
          <Heart />
          <UnsplashImage url={image.urls.thumb} key={image.id} />
          <p className="like"> Amount of Likes ❤️ {image.likes}</p>
          <Download downloadUrl={image.urls.full} />
        </Div>
      </>))}
    </WrapperImg>

Now you can go to the Download Component and edit it.

const Download = ({downloadUrl}) => {
const downloadImage = () => {
   saveAs(downloadUrl, 'image.jpg');
 } 

}
return <button onClick={downloadImage}>Download</button>

}

Here you don't need these code below

const imgURL = images.map((download) => {
//console.log(download.urls.full)
  return download.urls.full;
 });

Upvotes: 0

Aneesh
Aneesh

Reputation: 1715

This should help you:

// the download buttons with specific links will all be stored in the array returned here
const allYourDownloadButtons = images.map((download) => {
    let imgURL = download.urls.full;
    // saveAs was not mentioned in your code, if it's in scope here, you can directly pass it
    return <DownloadV2 imgURL={imgURL} saveAs={saveAs} />;
});

const DownloadV2 = ({ imgURL, saveAs }) => {
    return <button onClick={() => saveAs(imgURL, 'image.jpg')}>Download</button>;
};

Once you display the buttons on the UI, clicking on them will pass the specific URL through saveAs.

In case you need to know how to use this, please share in the question where you were calling this button.

A very generic way to use it would be like this:

<div className="allMyDownloadButtons">
    {allYourDownloadButtons}
</div>

Edit: based on your updates I can see that your job is even easier as you were already looping through the images:

<WrapperImg>
    <FileUpload />
    {images.map((image) => (
        <>
            <Div>
                <Heart />
                <UnsplashImage url={image.urls.thumb} key={image.id} />
                <p className="like"> Amount of Likes ❤️ {image.likes}</p>
                <DownloadV2 imgURL={image.urls.full} />
            </Div>
        </>
    ))}
</WrapperImg>

Upvotes: 0

kiranvj
kiranvj

Reputation: 34147

Try this to download each image, I have removed loop and modified the Download function

  const imgURL = images.map((download) => {
    //console.log(download.urls.full)
    return download.urls.full;
  });

    const downloadImage = (index) => {
       var red = imgURL[index];
        saveAs(red, 'image.jpg');    
    }


  return (
    <div className="App">
        <WrapperImg>
          {images.map((image,index) =>
          (<>
            <Div>
              <UnsplashImage url={image.urls.thumb} key={image.id} />
              <button onClick={()=> { downloadImage(index) }>Download</button>
            </Div>
          </>))}
        </WrapperImg>
    </div>
  );
}

Upvotes: 1

Related Questions