Problems with POST in React and Node.js

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;

Answer

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());