-1

I am trying to figure out what change I need to make to my flow where I am triggering a post call and on success return to run another fetch call followed by a 3rd party generated redirect (Stripe). At the moment I am receiving an error message at const session = await response.json() with the message:

Failed to execute 'json' on 'Response': body stream already read

and I'm not sure how to refactor my code to be able to handle this issue. Can anyone point to what is wrong with my current setup and the rules I might be breaking?

const signUp = (e) => {
  e.preventDefault();

  if (password === passwordConfirmation) {
    axios
      .post(
        "/api/auth/signup/",
        { email, password, passwordConfirmation },
        {
          headers: {
            "Content-Type": "application/json",
          },
          withCredentials: true,
        }
      )
      .then((res) => {
        const data = res.data;
        setUser(data.user);
        // Set the error message
        if (data.message.status === "error") {
          console.log("Error present");
          setMessage(data.message);
        }
        return data.message.status;
      })
      .then(async (serverMessage) => {
        // On successful sigin, redirect to /api/stripe/checkout-session/
        if (serverMessage !== "error") {
          // Get Stripe.js instance
          const stripe = await stripePromise;

          const response = await fetch("/api/stripe/checkout-session/", {
            method: "POST",
          });
          console.log(`response: ${response.json()}`);
          const session = await response.json();
          console.log(`session: ${session}`);

          // When the customer clicks on the button, redirect them to Checkout.
          const result = await stripe.redirectToCheckout({
            sessionId: session.sessionId,
          });
          // router.push('/api/stripe/checkout-session/')
          // router.push('/app/feed/')
        }
      })
      .catch((err) => {
        console.log(err);
        console.log(err.request);
        console.log(err.message);
      });
  } else {
    setMessage({
      status: "error",
      body: "Passwords do not match. Please try again.",
    });
  }
};
Phil
  • 157,677
  • 23
  • 242
  • 245
cphill
  • 5,596
  • 16
  • 89
  • 182
  • 1
    Why mix Axios and Fetch? Why `withCredentials`? Why redefine the [default headers Axios would send anyway](https://stackoverflow.com/a/73017821/283366)? – Phil Aug 16 '22 at 00:49
  • 2
    Just don't call `response.json()` twice! Remove the unnecessary `console.log` line, or only do `console.log(`response:', response);` – Bergi Aug 16 '22 at 00:49
  • @Phil I'm in the middle of porting all of my requests to Axios so pardon my sloppiness with usage of both – cphill Aug 16 '22 at 00:50
  • @Phil Really? I just pasted the error message into the StackOverflow search… – Bergi Aug 16 '22 at 00:52
  • @cphill keep porting and you wouldn't even have this error – Phil Aug 16 '22 at 00:55

2 Answers2

1

Do not call .json() twice.

change

   console.log(`response: ${response.json()}`);
   const session = await response.json();

to

   const session = await response.json();
   console.log(`response: ${session}`);
   
Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
-1

you can only read body stream once :) Try this

const signUp = (e) => {
  e.preventDefault();

  if(password === passwordConfirmation){
    axios.post('/api/auth/signup/', { email, password, passwordConfirmation }, {
      headers: {
        'Content-Type': 'application/json'
      },
      withCredentials: true
    }).then((res) => {
      const data = res.data;
      setUser(data.user)
      // Set the error message
      if(data.message.status === 'error'){
        console.log('Error present')
        setMessage(data.message)
      }
      return data.message.status
    }).then(async (serverMessage) => {
      // On successful sigin, redirect to /api/stripe/checkout-session/
      if (serverMessage !== 'error'){
        // Get Stripe.js instance
        const stripe = await stripePromise;

        const response = await fetch('/api/stripe/checkout-session/', { method: 'POST' });
        const responseBody = await response.json()
        console.log(`response: ${responseBody}`);
        const session = responseBody;
        console.log(`session: ${session}`);

        // When the customer clicks on the button, redirect them to Checkout.
        const result = await stripe.redirectToCheckout({
          sessionId: session.sessionId,
        });
        // router.push('/api/stripe/checkout-session/')
        // router.push('/app/feed/')
      }
    }).catch((err) => {
      console.log(err)
      console.log(err.request)
      console.log(err.message)
    })
  } else {
    setMessage({
      'status': 'error',
      'body': 'Passwords do not match. Please try again.'
    })
  }
}
MisieQQQ
  • 226
  • 1
  • 6