Sending Data from React to MySQL
Asked Answered
S

4

9

I am creating a publishing application that needs to use communication between React and MySQL database to send information back and forth. Using Express as my JS server. The server code looks as follows:

const express = require('express');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const cors = require('cors');
const connection = mysql.createConnection({
   host     : 'localhost',
   user     : 'root',
   password : '',
   database : 'ArticleDatabase',
   port: 3300,
   socketPath: '/Applications/XAMPP/xamppfiles/var/mysql/mysql.sock'
  });

// Initialize the app
const app = express();
app.use(cors());

appl.post('/articletest', function(req, res) {
   var art = req.body;
   var query = connection.query("INSERT INTO articles SET ?", art,    
      function(err, res) {
         })
   })

// https://expressjs.com/en/guide/routing.html
app.get('/comments', function (req, res) {
// connection.connect();

connection.query('SELECT * FROM articles', function (error, results,  
  fields) {
    if (error) throw error;
    else {
         return res.json({
            data: results
         })
    };
});

//    connection.end();
});

// Start the server
app.listen(3300, () => {
   console.log('Listening on port 3300');
 });

And my React class looks as follows:

class Profile extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        title: '',
        author: '',
        text: ''
    }
}

handleSubmit() {
    // On submit of the form, send a POST request with the data to the  
    //  server.
    fetch('http://localhost:3300/articletest', {
        body: JSON.stringify(this.state),
        cache: 'no-cache',
        credentials: 'same-origin',
        headers: {
            'content-type': 'application/json'
        },
        method: 'POST',
        mode: 'cors',
        redirect: 'follow',
        referrer: 'no-referrer',
    })
        .then(function (response) {
            console.log(response);
            if (response.status === 200) {
                alert('Saved');
            } else {
                alert('Issues saving');
            }
        });
}

render() {
   return (
    <div>
      <form onSubmit={() => this.handleSubmit()}>
        <input type = "text" placeholder="title" onChange={e =>  
           this.setState({ title: e.target.value} )} />
        <input type="text" placeholder="author" onChange={e => 
          this.setState({ author: e.target.value} )}  />
        <textarea type="text" placeholder="text" onChange={e => 
          this.setState({ text: e.target.value}  )} />
        <input type="Submit" />
      </form>
   </div>
   );
  }
}

So fairly standard stuff that I found in online tutorials. I can search my database and display fetched info no problem, but not the other way around. When I try to take input from the <form> tag nothing is inserted into my database but instead I get this error:

[Error] Fetch API cannot load    
http://localhost:3000/static/js/0.chunk.js due to access control 
checks.
Error: The error you provided does not contain a stack trace.
Unhandled Promise Rejection: TypeError: cancelled

I understand that this has something to do with access control but since I am already using cors and can successfully retrieve data from the database, I am not sure what I am doing wrong. Any suggestions will be greatly appreciated. Thank you in advance.

Shumway answered 2/5, 2019 at 4:38 Comment(2)
Did you check you're getting values of fields while submitting form ? In state? Also Make sure you're getting exact data in your router callback function. I tested the same code within my application with postgresSQL database and react component. It worked like charm.Mcdonnell
Alexander, would you mind posting the bounty? Thank you.Jinni
J
5

You'll need to isolate the problem by first verifying that your service point is CORS Enabled. In order to focus solely on CORS functionality, I would remove the MySQL code temporarily.

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');

const app = express();
app.use(cors());

app.get('/', function(req, res){
  var root = {};
  root.status = 'success';
  root.method = 'index';
  var json = JSON.stringify(root);
  res.send(json);
});

app.post('/cors', function(req, res) {
  var root = {};
  root.status = 'success';
  root.method = 'cors';
  var json = JSON.stringify(root);
  res.send(json);
})

// Start the server
app.listen(3300, () => {
   console.log('Listening on port 3300');
 });

One you have server listening on port 3300, run the following PREFLIGHT command at the terminal.

curl -v \
-H "Origin: https://example.com" \
-H "Access-Control-Request-Headers: X-Custom-Header" \
-H "Acess-Control-Request-Method: POST" \
-X OPTIONS \
http://localhost:3300

If the preflight request is successful, the response should include Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers

Now run the POST method.

curl -v \
-H "Origin: https://example.com" \
-H "X-Custom-Header: value" \
-X POST \
http://localhost:3300/cors

If the post request is successful, the response should include Access-Control-Allow-Origin

If everything looks good, your server is okay. You then need to try the post method from your iOS app.

NOTE. I would also be suspicious of using cors on localhost. I would map 127.0.0.1 to a domain and then have the app use that domain instead. If you are on Linux or Mac, you modify /etc/hosts. For Windows it's c:\windows\system32\drivers\etc\hosts

Jinni answered 14/5, 2019 at 16:50 Comment(2)
Yep, everything runs as you said, I get the correct responses but when I try to post from the React app it still gives me the same error.Shumway
Ok I will have to spin up React code in order to troubleshoot that part.Jinni
L
1

Try explicitly whitelisting the server that is making the request:

const whitelist = ['http://localhost:3000']; // React app

const corsInstance = cors({
  origin: (origin, callback) => {
    if (!origin || whitelist.indexOf(origin) !== -1) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  }
});

application.use(corsInstance);

https://expressjs.com/en/resources/middleware/cors.html#configuring-cors-w-dynamic-origin

Lavine answered 9/5, 2019 at 16:59 Comment(3)
Inserted the above code into my server.js file, still the same error unfortunately...Shumway
@AlexanderNenartovich Does it log the Not allowed by CORS error? If so, try logging the origin to see what's getting rejected.Lavine
It logs the exact same error I showed above - Fetch API can not load localhost:3000... due to access control checks. It says nothing specifically about CORS.Shumway
G
1

You need to add event.preventDefault() at the end of your handleSubmit method (check this example https://stackblitz.com/edit/react-forms).

You have to do it for the reason for preventing form default behavior on submit: it tries to synchronously send data to the url it loaded from (since there is no action attribute on it).

Ghent answered 14/5, 2019 at 16:23 Comment(5)
Doesn't work, sorry. Error, cannot evaluate property of undefined (event is not defined).Shumway
It works on StackBlitz and should work in your app. It's likely that you didn't pass event parameter to handleSubmit method.Ghent
I did pass the event parameter. Now there are no errors but nothing happens. Nothing is inserted into database and nothing is sent to the server. No idea what is going on.Shumway
You are correct, passing the event parameter to handleSubmit took care of that undefined error but now when I cluck the submit button simply nothing happens. No errors and no data being sent or inserted anywhere I can see.Shumway
You just saved me another week of trying to solve this. Here is a more detailed solution based on your answer just in case anyone would ever need this: https://mcmap.net/q/1317655/-capacitor-on-ios-post-request-failsBoletus
S
0

For those who may have run into a similar problem, I was able to fix it by dumping express server altogether. I simply used the .php file on the Apache server to insert data into database. Hope it helps somebody.

Shumway answered 25/5, 2019 at 19:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.