Search code examples
reactjsasynchronouspostxmlhttprequest

useEffect wait for a result from the async function


I'm trying to create a function for POST request in React app (due to I need it in few places), it should return a responseText in the useEffect statement. the variant I've googled doesn't act as async - the string console.log("JSON", json) put into the console JSON undefined before the getting response from server...

useEffect(() => {
        (async function() {
            try {
                const response = await post_return(postData);
                const json = await JSON.stringify(response);
                console.log("json", json);
            } catch (e) {
                console.error(e);
            }
        })();
    }, [postData]);
const API_URL_REGISTRATION = "https:.....";

export function post_return (dataPost)  {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", API_URL_REGISTRATION, true);

    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

    xhr.onreadystatechange = function () {
        if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
            console.log("xhr.status", this.status);
            console.log("this.responseText", this.responseText);
            return  xhr.status
        }
    };
    xhr.onload = function () {
        console.log("xhr.status", this.status);
        console.log("this.responseText", this.responseText);
        return  xhr.status;
    };

    xhr.onerror = function () {
        alert('Error' + this.status);
    };
    xhr.send(JSON.stringify(dataPost));
}

tried also:

export async function post_return (dataPost) {...

and:

xhr.onreadystatechange = async function ()

What I do wrong? Thanks,


Solution

  • First thing that is wrong with post_return function is it returns undefined immediately, hence the response variable value is actually undefined and a result of calling JSON.stringify with undefined is also undefined. What you should do is to correct post_return so that it returns a Promise.

    Simplest solution would be to use built-in fetch like so:

    export function async post_return (dataPost)  {
      const response = await fetch(API_URL_REGISTRATION, {
        method: 'POST',
        body: JSON.stringify(dataPost),
        headers: {
          'Content-type': 'application/x-www-form-urlencoded'
        }
      });
      
      if (response.ok) {
        return response.json();
      }
      
      // Here you can do some basic error parsing/handling
      throw new Error();
    }