I am trying to save images to indexeddb and then fetch and display them in a react app. My approach is to convert images to a blob and save the blob url to indexeddb and then when it's time to display, fetch the blob url and set the image url as .src.
How I created the blob
fetch(imgurl, {
mode: 'no-cors',
method: "get",
headers: {
"Content-Type": "application/json"
}
})
.then(response => response.blob())
.then(async images => {
var blob_url = URL.createObjectURL(images)
var blobA = blob_url.replace("blob:","")
var blobB = blobA.replace('"','')
I am trying to save images to indexeddb and then fetch and display them in a react app. My approach is to convert images to a blob and save the blob url to indexeddb and then when it's time to display, fetch the blob url and set the image url as .src.
How I created the blob
fetch(imgurl, {
mode: 'no-cors',
method: "get",
headers: {
"Content-Type": "application/json"
}
})
.then(response => response.blob())
.then(async images => {
var blob_url = URL.createObjectURL(images)
var blobA = blob_url.replace("blob:","")
var blobB = blobA.replace('"','')
this is bloburl blob:http://localhost:3000/d7a55f39-b496-476b-8c3c-857874bd107c
I then remove blob: and save this url in indexeddb to be fetched when needed http://localhost:3000/d7a55f39-b496-476b-8c3c-857874bd107c
this is where I need to use the blob image
import React from "react";
import { Row, Col, Container, Image } from 'react-bootstrap';
function Item({ item }) {
const imgurl = item.productimg
fetch(imgurl)
.then(res => res.blob()) // Gets the response and returns it as a blob
.then(async blob => {
const test = await blobToImage(blob)
console.log("image test",test)
let objectURL = URL.createObjectURL(blob);
let myImage = document.getElementById('myImg')
myImage.src = objectURL;
});
return (
<div className="item" id={item.id}>
<Row>
<Col>
<Image id="myImg" width="50" height="58" rounded />
</Col>
<Col xs={6}>
<div className="item-info">
<p>{item.name}</p>
</div>
</Col>
<Col>3 of 3</Col>
</Row>
<div className="item-actions">
<button className="btn-remove">X</button>
</div>
</div>
);
}
export default Item;
Item contains all the productdata including the saved blob url. The problem is the images are not showing and I could not figure out why.
what could i be doing wrong and how can I display the images
Share Improve this question edited Mar 12, 2021 at 17:03 e.iluf asked Mar 12, 2021 at 13:39 e.ilufe.iluf 1,6597 gold badges32 silver badges81 bronze badges2 Answers
Reset to default 7Don't modify the Blob
's URL.
When you took the blob:
part out of the URL string to the Blob
, the browser no longer knew that you were referencing your Blob
. Instead, try leaving the URL alone after creating it with URL.createObjectURL
.
On top of that, when synchronizing a ponent with an external resource (like fetching data), you should use React's useEffect
hook.
Example with React
You can view this example live at StackBlitz.
function Item({ item }) {
const imgURL = item.productimg;
const [blobURL, setBlobURL] = React.useState(null);
React.useEffect(() => {
const controller = new AbortController(); // https://developer.mozilla/en-US/docs/Web/API/AbortController
const signal = controller.signal;
fetch(imgURL, { signal })
.then((res) => res.blob()) // Get the response and return it as a blob
.then((blob) => { // Create a URL to the blob and use it without modifying it.
setBlobURL(URL.createObjectURL(blob));
})
.catch((error) => { // Error handling here
console.error(error);
});
// Cancel the fetch request on any dependency change
return () => controller.abort();
}, [imgURL]);
return (
<div className="item" id={item.id}>
<Row>
<Col>
{blobURL ? <Image src={blobURL} id="myImg" width="50" height="58" rounded /> : <p>Loading...</p>}
</Col>
<Col xs={6}>
<div className="item-info">
<p>{item.name}</p>
</div>
</Col>
<Col>3 of 3</Col>
</Row>
<div className="item-actions">
<button className="btn-remove">X</button>
</div>
</div>
);
}
Example with plain JavaScript
const imgURL = "https://cdn62.picsart./182788826000202.jpg?type=webp&to=crop&r=256"
fetch(imgURL)
.then(response => response.blob())
.then(blob => {
document.getElementById('my-img').src = URL.createObjectURL(blob)
})
<img id="my-img" />
Good Luck...
The URL lifetime is tied to the document in the window on which it was created.. ObjectURL is not meant to be saved somewhere. You can convert your image to base64 and store as data-uri instead.