(React question) Updating parameter in cloud function before call

While passing a parameter to a cloud function, it always passes the one previous state. I am trying to fetch the image which is currently rendered on a canvas and pass it to a cloud function in another component. Even though I’m using useState and useEffect I am unable to get the immediate canvas state. It always passes the image that was one prior to current state. I assume this is happening because the value is captured then the component having the cloud function renders. And subsequent change to the canvas would require a re-render of the cloud function component in order for it to capture the latest value?

  1. I am getting the base64 value from the canvas of one component like this:
        let imageToSave = new Image();
        imageToSave.src = canvas.current.toDataURL('image/png', 1.0)
        return imageToSave.src
        }
  1. I wish to pass it as a parameter in a cloud function call in another component. For which I am doing this:
const [finalImage, setFinalImage] = useState(null)
const { fetch:cloudFetch } = useMoralisCloudFunction(
      "handlemint",
      {
        autoFetch: false,
        userAddress: userAddress,
        image: finalImage
    }
  1. Now I have tried all kinds of ways to setFinalImage(props.saveImage()) to pass the base64 into image parameter before my function call. I’ve tried useEffect, I have aaded setFinalImage inside a function and tried to update the value BEFORE I call the cloud function…
async function updateFinalImage(image) {
        setFinalImage(image)
      }
const cloudCall = async ()=>{
        const image = await props.saveImage()
        await updateFinalImage(image)
        await cloudFetch({
          onSuccess: (data)=>console.log(data)
        })
      }

I have tried both regular and async for all this. No matter what I do, the value passed into my image parameter is always one step behind . So if I have a dog picture on canvas, the null value gets passed in. Then when I change dog to cat pic on canvas, the dog (previous picture) gets passed in.

My saveImage function is not lagging. If I console log it in child component it gives me whatever latest value is on the canvas. Somehow while passing into the cloudCall with useState update, always the previous value goes and not the current updated value. I have tried to circumvent the asynchronous nature of useState by putting it inside the function but nothing works. What am I doing wrong?

My question is how do I fetch the base64 from parent component’s function saveImage() and pass it in the cloud function as image: finalImage in a way that it takes the LATEST update always when I call the cloud function. Right now trying useState to update the value of image is ALWAYS sending the previous value.

I have seen @YosephKS address a similar question here but that was a simpler use case involving some text field.

Edit: Here is a codesanbox link to better understand. Board.jsx line 149. Is the function which saves whatever is on current canvas.
Here in Mint.jsx line 40 is where I wish to pass that image into, as a parameter to the cloud function.

SOLVED IT! after 3 days of racking my head!

function saveImage() {
        let imageToSave = new Image();
        imageToSave.src = canvas.current.toDataURL('image/png', 1.0)
        imageToSave.onload= () => {
        return imageToSave.src
        }
        }

I added the return call inside an onload event. This way it ONLY returns AFTER the new (latest) image has loaded on canvas and not prematurely. Doing this solved my problem of premature return, which was the reason my base64 for was always one render behind what was ACTUALLY on canvas.

2 Likes