Reputation: 15
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
Reputation: 1
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);
})
<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>
const Download = ({downloadUrl}) => {
const downloadImage = () => {
saveAs(downloadUrl, 'image.jpg');
}
}
return <button onClick={downloadImage}>Download</button>
}
const imgURL = images.map((download) => {
//console.log(download.urls.full)
return download.urls.full;
});
Upvotes: 0
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
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