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
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 component with an external resource (like fetching data), you should use React's useEffect
hook.
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.org/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>
);
}
const imgURL = "https://cdn62.picsart.com/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...