简体   繁体   中英

React Custom Hook make return Function executable on an Event

I have created a custom hook for handling the uploads to AWS s3 bucket but I am facing a small problem. I did not want my hook to execute the logic directly so I created an executable function that I am then returning. The only problem is that the state is not being set from inside the handleUpload function

Here is what I am trying to do:

import React, { useState } from "react";

const useS3Aws = () => {
  const [isLoading, setIsLoading] = useState(false);
  const [uploadedUrl, setUploadedUrl] = useState("");


  const handleUpload = async (file: any, s3FolderPath: string) => {
    setIsLoading(true); // the problem is here (state not being updated)

    // handle the uploading with AWS s3
    // code ......

    // setting the state with returned live url from s3
    setUploadedUrl("the live url"); // the problem is here (state not being updated)
    console.log(uploadedUrl); // it prints an empty string

    setIsLoading(true); // the problem is here (state not being updated)

  };

  return [
    isLoading,
    uploadedUrl,
    (file: any, s3FolderPath: string) => handleUpload(file, s3FolderPath),
  ] as const;
};

const UploadSong = () => {
  const [isLoading, uploadedUrl, handleUpload] = useS3Aws();

  const handleSong = async () => {

    const file = {
      // object data
    };


    handleUpload(file, "music");

    console.log(uploadedUrl); // it is empty

  };

  return (
    <div>
      <p>Live URL: {uploadedUrl ? uploadedUrl : "No Link"}</p>
      <button onClick={() => handleSong()}>
        Click me
      </button>
    </div>
  );
}

export default UploadSong;

Playground Link

Your hook looks fine, but you aren't using it's returned values right.

<button onClick={() => handleSong}>

That doesn't actually call handleSong on click. This calls a function that merely returns the handleSong function on click.

You want:

<button onClick={() => handleSong()}>

Or if you don't want to pass arguments, you can just:

<button onClick={handleSong}>

One point where you may be confused here:

console.log(uploadedUrl); // it is empty

When you set state, it's asynchronous. State is being set properly, but any local variables will reflect the previous state, because the re-render has not yet happened. Usually this doesn't matter at all, because as you can see here the UI updates immediately when you click the working button.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM