0

I have the following synchronism problem. Given that I know that the React useState hook is asynchronous, I run into the following: I'm downloading some images from Amazon S3, I manage to save it correctly in my hook: defaultSelfiePicture and depending on the weight of the image (or so I think) sometimes I get the images loaded correctly and sometimes not. I have tried to force state changes after I finish saving the object in my hook but it never renders the image, only if I change component and come back is when it is shown in the cases that it takes longer to load.

const [defaultSelfiePictures, setDefaultSelfiePictures] = useState([])


useEffect(() => {
    if (savedUser.docs !== undefined) {         
        loadAllPictures()
    }
}, [savedUser.docs.length])

const loadAllPictures = () => {
    let p1 = loadUrlDefaultFrontPictures()
    let p2 = loadUrlDefaultBackPictures()
    let p3 = loadUrlDefaultSelfiePictures()

    Promise.all([p1, p2, p3]).then(result => {
        console.log('end all promises')
        setTimestamp(Date.now())
    })
}

const loadUrlDefaultSelfiePictures = async () => {
    if (savedUser.docs.length > 0) {
        let readedPictures = []
        for (let i = 0; i < savedUser.docs.length; i++) {
            if (
                savedUser.docs[i].type === 'SELFIE'
                //&&                    savedUser.docs[i].side === 'FRONT'
            ) {
                if (
                    savedUser.docs[i].s3Href !== null &&
                    savedUser.docs[i].s3Href !== undefined
                ) {
                    const paramsKeyArray =
                        savedUser.docs[i].s3Href.split('')
                    let paramsKey = paramsKeyArray.pop()

                    let params = {
                        Bucket: process.env.REACT_APP_S3_BUCKET,
                        Key: paramsKey
                    }

                    await s3.getSignedUrl('getObject', params, function (err, url) {
                        readedPictures.push({
                            idKycDoc: savedUser.docs[i].idKycDoc,
                            name: 'selfie.jpeg',
                            type: savedUser.docs[i].type,
                            url: url
                        })
                    })

                
                } else {
                    
                    let urlPicture = savedUser.docs[i].localHref
                    let response = await axios.get(`${URL_IMG}${urlPicture}`, {
                        responseType: 'blob'
                    })
                    
                    function readAsDataURL(data) {
                        return new Promise((resolve, reject) => {
                            const reader = new FileReader()
                            reader.readAsDataURL(data)
                            reader.onloadend = () => {
                                resolve(reader.result)
                            }
                        })
                    }

                    const base64Data = await readAsDataURL(response.data)

                    readedPictures.push({
                        idKycDoc: savedUser.docs[i].idKycDoc,
                        name: 'selfie.jpeg',
                        type: savedUser.docs[i].type,
                        url: `data:image/jpeg;base64,${base64Data.slice(21)}`
                    })
                }
            }
        }

        setDefaultSelfiePictures(readedPictures)
        
    }
    
}

And I obtain this :

enter image description here

I can see that the hook has content, but that content is not updated until the next rendering of the component, also if I try to make any changes when I detect that the .length has changed it tells me that it is 0... And right after the next render I get this:

enter image description here

skyboyer
  • 22,209
  • 7
  • 57
  • 64
Raul
  • 659
  • 1
  • 6
  • 11

0 Answers0