Search code examples
reactjsapierror-handlingrequestsendinblue

Getting back a response or error from a function call that makes api request


I try to make a api request to Sendinblue to create a new contact. And the code I have works but the problem is that I don't get the error handling right.

I have created a component and in another file I created the function that makes the request. The function gets called on form submit, the result is assigned to a variable and an if/else based on the variable's value should display a message to the user(it this moment just a log to check).

Currently the 'result' variable is always undefined within the if/else, which is logical because the request takes some time. But I can't figure out how I can make it work.

Things I tried:

  • Instead of the if/else use a then/catch.
  • Made the saveContact function a async function.

Component:

import React, { useState } from "react";
import saveContact from "../js/form";

function Form() {
  const [firstname, setFirstname] = useState("");
  const [lastname, setLastname] = useState("");
  const [email, setEmail] = useState("");
  const [error, setError] = useState(false);
  const [succes, setSucces] = useState(false);
  const errorMessage = error
    ? "Something went wrong, sorry. Try again later."
    : "";
  const succesMessage = succes ? "Thank you, subscribed succesfully!" : "";

  const handleForm = (e) => {
    e.preventDefault();
    const result = saveContact(firstname, lastname, email);
    console.log(result);
if (result) {
  console.log("Created");
} else {
  console.log("Error");
}
  };

  return (
    <div className="row">
      <div className="col-lg-8 mx-auto">
        <form
          id="contactForm"
          name="sentMessage"
          noValidate="novalidate"
          onSubmit={handleForm}
        >
          <div className="control-group">
            <div className="form-group floating-label-form-group controls mb-0 pb-2">
              <label>Firstname</label>
              <input
                className="form-control"
                id="firstname"
                type="text"
                placeholder="Firstname"
                required="required"
                value={firstname}
                onChange={(e) => setFirstname(e.target.value)}
                data-validation-required-message="Please enter your firstname."
              />
              <p className="help-block text-danger"></p>
            </div>
          </div>
          <div className="control-group">
            <div className="form-group floating-label-form-group controls mb-0 pb-2">
              <label>Lastname</label>
              <input
                className="form-control"
                id="lastname"
                type="text"
                placeholder="Lastname"
                required="required"
                value={lastname}
                onChange={(e) => setLastname(e.target.value)}
                data-validation-required-message="Please enter your lastname."
              />
              <p className="help-block text-danger"></p>
            </div>
          </div>
          <div className="control-group">
            <div className="form-group floating-label-form-group controls mb-0 pb-2">
              <label>Email Address</label>
              <input
                className="form-control"
                id="email"
                type="email"
                placeholder="Email Address"
                required="required"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                data-validation-required-message="Please enter your email address."
              />
              <p className="help-block text-danger"></p>
            </div>
          </div>
          <br />
          <div id="success">{succesMessage}</div>
          <div id="success">{errorMessage}</div>
          <div className="form-group">
            <button
              className="btn btn-primary btn-xl"
              id="sendMessageButton"
              type="submit"
            >
              Send
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

export default Form;

Function that makes the request:

var request = require("request");

function saveContact(firstname, lastname, email) {
  var options = {
    method: "POST",
    url: "https://api.sendinblue.com/v3/contacts",
    headers: {
      accept: "application/json",
      "content-type": "application/json",
      "api-key":
        <api-key>,
    },
    body: {
      listIds: [4],
      updateEnabled: false,
      email: email,
      emailBlacklisted: false,
      smsBlacklisted: false,
      attributes: {
        LASTNAME: firstname,
        FIRSTNAME: lastname,
      },
    },
    json: true,
  };

  try {
    request(options, function (error, response, body) {
      if (error) {
        throw new Error(error);
      } else {
        return body;
      }
    });
  } catch (error) {
    return error;
  }
}

export default saveContact;

Solution

  • After some searching I finally found the answer.

    In the function that makes the request I added a callback and returned the function, like this:

    const response = request(options, function (error, response, body) {
        if (error) {
          callback(error);
        } else {
          callback({ body, response });
        }
      });
    
      return response;
    

    And in the component a had to make a async completion function with if/else in the body, like this:

    const handleForm = (e) => {
        e.preventDefault();
    
        saveContact(firstname, lastname, email, async (result) => {
          if (result.response.statusCode === 201) {
            const result = await user.functions.updateUserCount();
            // console.log("RESULT", result);
            setSucces("Thank you, subscribed succesfully!");
            setErrorMessage("");
            setFirstname("");
            setLastname("");
            setEmail("");
            setUserCount(userCount + 1);
          } else {
            setErrorMessage("Something went wrong, sorry. Try again later.");
          }
        });