1

I am trying to display images for each country code that i am using for my API (ALPHA_3 array) in a React component. getFlags() and appendImg() are imported and executed in a component, but it looks like the imgs are broken/non-existent.

I found an API (countryflags.io) that provides png's for each country i use - but it uses alpha2 naming. In order to fetch the countryflags API i that uses ALPHA2, i slice my ALPHA_3 array and for each country code in the array i make a fetch request. Everything is saved to localestorage using the alpha2 code as key and blob as value.

When i try to display the blobs they appear as broken images and i cant figure out what causes this. Also, is there a better way to store blobs or is localestorage just fine?

                const ALPHA_3 = [
                'CAD',
                'HKD',
                'ISK',
                'PHP',
                'DKK',
                'HUF',
                'CZK',
                'AUD',
                'RON',
                'SEK',
                'IDR',
                'INR',
                'BRL',
                'RUB',
                'HRK',
                'JPY',
                'THB',
                'CHF',
                'SGD',
                'PLN',
                'BGN',
                'TRY',
                'CNY',
                'NOK',
                'NZD',
                'ZAR',
                'USD',
                'MXN',
                'ILS',
                'GBP',
                'KRW',
                'MYR',
            ];

            const base_url = 'https://www.countryflags.io';
            const opts = { mode: 'no-cors', 'Content-Type': 'image/png' };
            const ALPHA_2 = [];

            const getFlags = () => {
                ALPHA_3.forEach((element) => ALPHA_2.push(element.slice(0, -1)));
                ALPHA_2.forEach((element) => {
                    fetch(base_url + `/${element}/flat/32.png`, opts)
                        .then((response) => response.blob())
                        .then((png) =>
                            localStorage.setItem(`${element}`, URL.createObjectURL(png))
                            
                        );
                });
            };
            export default getFlags;


            export const appendImg = () => {
                Object.values(localStorage).forEach((v) => {
                    let image = document.createElement(`img`);
                    image.src = v;
                    document.body.appendChild(image);
                });
            };
APV
  • 53
  • 2
  • 6
  • 1
    `URL.createObjectURL(...)` will break after refresh. You should instead either A) (recommended) Use [localForage](https://github.com/localForage/localForage) instead which allows you to save blobs or B) [Encode the image](https://stackoverflow.com/questions/6150289/how-can-i-convert-an-image-into-base64-string-using-javascript) to base64 and [decode](https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript) when using it. – Nate Levin Oct 22 '20 at 17:57
  • 1
    Keep in mind that localStorage has quotas. Something like 10MB per domain (might be even smaller in some browsers). You might want to take a look on [Cache API](https://developer.mozilla.org/en-US/docs/Web/API/Cache) instead. – Yury Tarabanko Oct 22 '20 at 18:05

1 Answers1

1

Thanks for the heads up about limited storage in localestorage and that URL.createObjectURL() breaks on refresh. I refactored the code to use the Cache API and managed to save the alpah2 code for each rates along with the response as a key-value pair in the cache, using PUT method because no-cors. Now i wonder, how i can access the cache and display it in the browser from another file/react component.

            const ALPHA_3 = [
            'CAD',
            'HKD',
            'ISK',
            'PHP',
            'DKK',
            'HUF',
            'CZK',
            'AUD',
            'RON',
            'SEK',
            'IDR',
            'INR',
            'BRL',
            'RUB',
            'HRK',
            'JPY',
            'THB',
            'CHF',
            'SGD',
            'PLN',
            'BGN',
            'TRY',
            'CNY',
            'NOK',
            'NZD',
            'ZAR',
            'USD',
            'MXN',
            'ILS',
            'GBP',
            'KRW',
            'MYR',
        ];

        const cacheFlags = async () => {
            const imageCache = await caches.open('imageCache');
            if (imageCache.keys().length >= 32) return false; 
            const base_url = 'https://www.countryflags.io';
            const opts = { mode: 'no-cors', 'Content-Type': 'image/png' };
            const ALPHA_2 = [];
            ALPHA_3.forEach((element) => ALPHA_2.push(element.slice(0, -1)));
            ALPHA_2.forEach((element) => {
                let url = base_url + `/${element}/flat/32.png`;
                fetch(url, opts)
                    .then((response) => {
                        imageCache.put(element, response);
                    })
                    .catch((error) => error);
            });
        };
        export default cacheFlags;

enter image description here

APV
  • 53
  • 2
  • 6