0

I'm learning how to combine Node and React. The current thing that I'm working on is posting to Node from inputs in a React form.

I'm having two problems:

  1. I'm getting Promise pending (it has {<>} around the pending but I can't figure out how to put that on here without it being read as code) on the async/await fetch request. If I change it to fetch().then().then() I don't get the problem anymore, but I want to figure out how to do it this way too.

  2. I'm getting an error of "Uncaught (in promise) SyntaxError: Unexpected token P in JSON at position 0" as well.

I'm pretty sure that the problem is on the React side. I got the whole thing working before, but I deleted it and started over because that's what I do when I'm learning. I obviously had something slightly different in my code before. I could use tutorials and websites to figure out how to write this kind of request so that it works, but maybe I wouldn't figure out what was going wrong this time and it would drive my crazy. Obviously there are more things to do on the Node side in order to get the data to the database (I got the data into Node before), but I'm trying to figure this out before that.

server.js

const express = require('express');
const application = express();
const cors = require('cors');
application.use(cors());
application.use(express.json());
application.use(express.urlencoded({ extended: true }));

// routes are here
application.get('/', (request, response) => {
    response.send('Homepage');
});
application.get('/testAPI', (request, response) => {
    response.json('Test API working');
});
application.get('/register', (request, response) => {
    response.send('Register route');
});
application.post('/register', (request, response) => {
    response.send('POST received');
    console.log('POST received');
});

// listen to server
application.listen(8080, () => {
    console.log('Listening here...');
});

App.js

import { useState, useEffect } from 'react';

function App() {
  // basic state for things
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [data, setData] = useState('Data goes here');
  const [API, setAPI] = useState('Data from API goes here');

  useEffect(() => {
    fetch('http://localhost:8080/testAPI')
      .then(res => res.json())
      .then(data => setAPI(data));
  }, []);

  const readUsername = (e) => {
    setUsername(e.target.value);
  };

  const readPassword = (e) => {
    setPassword(e.target.value);
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    const inputData = {
      username: {username},
      password: {password},
    };
    const requestCall = {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(inputData),
    };
    const result = await fetch('http://localhost:8080/register', requestCall);
    console.log(result.json());
  };

  return (
    <div>
      <>
      <h1>Hello World!</h1>
      <form onSubmit={handleSubmit} method="POST">
        <label htmlFor="username" name="username" >Username: </label>
        <input htmlFor="username" name="username" onChange={readUsername} />
        <br/>
        <label htmlFor="password" name="password" >Password: </label>
        <input htmlFor="password" name="password" type="password" onChange={readPassword} />
        <br/>
        <button type="submit">Submit</button>
      </form>
      <h1>{API}</h1>
      </>
    </div>
  );
}

export default App;
0

1 Answer 1

3

The server is sending back text, not JSON. So any time you do this:

res.json()

You'll get that error. Replace those instances with this:

res.text()

Additionally, this is going to log the promise to the console:

console.log(result.text());

Because .text() (and .json()) is an asynchronous operation. Await its results:

console.log(await result.text());
Sign up to request clarification or add additional context in comments.

5 Comments

Great, thank you. But don't I want it in JSON? That's the way to documentation and samples I've found have it. How would I do that?
@phershbe: If you want JSON then your server should return JSON. Currently the server just returns text: response.send('POST received'); A simple example of returning JSON might be something like: response.json({ message: 'POST received' }); Then on the client you can use result.json() to parse the response and the result of that operation would be an object with a message property.
Okay great. I have two other questions for you or whomever. 1. In the documentation, it doesn't await again when doing return response.json() ... developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch ... why is that? 2. Why is my response returning {"username":{"username":"aa"},"password":{"password":"zz"}}? In my "inputData" array, it seems like I'm putting it in so that it will say {username: "aa", password: "zz"}, which is obviously what I want.
@phershbe: 1) It is awaiting the result, it's just not using the await keyword. Instead, it returns the result as another promise and appends another .then() to it. Exactly like you do in your useEffect operation. 2) What response are you referring to? That may be something for a new Stack Overflow question, focusing specifically on that operation and where that data comes from.
The response that I meant is the data that I console.log() after the fetch post request. I created a question and posted it here: stackoverflow.com/questions/68915738/… I tried to post it not long after the answers here, but I had to wait 90 minutes to ask another question since the points on my profile aren't high enough yet.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.