0

I am trying to build login with react.js and connect it to my springboot.

Here is my code, react.js:

import React from 'react';


export default class Login extends React.Component {
constructor() {
    super();
    this.state = {
        login:"",
        password:""
    }
}

// This will be called when the user clicks on the login button
login(e) {
    e.preventDefault();
    console.log(this.state.password)

    function createCORSRequest(method, url) {
        var xhr = new XMLHttpRequest();
        if ("withCredentials" in xhr) {

            // Check if the XMLHttpRequest object has a "withCredentials" property.
            // "withCredentials" only exists on XMLHTTPRequest2 objects.
            xhr.open(method, url, true);

        } else if (typeof XDomainRequest != "undefined") {

            // Otherwise, check if XDomainRequest.
            // XDomainRequest only exists in IE, and is IE's way of making CORS requests.
            xhr = new XDomainRequest();
            xhr.open(method, url);

        } else {

            // Otherwise, CORS is not supported by the browser.
            xhr = null;

        }
        return xhr;
    }

    var xhr = createCORSRequest('POST', "http://localhost:8080/test/login");
    if (!xhr) {
        throw new Error('CORS not supported');
    }
        fetch().then(r => r.json())
            .then(data => console.log(data))
            .catch(e => console.log(e))
}

render() {

    return (
        <form role="form">
            <div>
                <input type="text" name="login" placeholder="Username" />
                <input type="password" name="password" placeholder="Password" />
            </div>
            <button type="submit"onClick={this.login.bind(this)}>Login</button>
        </form>
    );
}
}

And this is my springboot code that is located as TestController:

@RestController
public class TestController {

@RequestMapping(value = "/test/login", method = RequestMethod.GET )
public Boolean testLogin(@RequestParam String login, @RequestParam String password) {
    if ( login.equals ("ajt"))

    return true;
    else {
        return false;
    }
}

Each of them are present in two different ports, react on :9000 and springboot on :8080.

Also, on my react page I get the error:

TypeError: Failed to execute 'fetch' on 'Window': 1 argument required, but only 0 present.(…)

Any ideas?

for info: I have only got 6 months coding behind me -_- please be kind!

Santa Clauze
  • 163
  • 1
  • 17

1 Answers1

0

There's a handful of small mistakes here. I'll try to point you in the right direction for a few of them.

First of all, I just wouldn't use fetch. It's listed as an expiremntal technology by MDN, and it's browser support is weak. For someone just starting out with web development, you're much better off using a more established and "safe" technology. Either simple XMLHTTP ajax or using the ajax method from jquery. You already seem to be going down the path of XMLHTTP, so I would suggest just replacing your fetch commands with the example I linked above.

Second, you're using two different HTTP methods. Your ajax object is going to send a POST command, but your server is listening for a GET command. This is set up on the following lines;

var xhr = createCORSRequest('POST', "http://localhost:8080/test/login");

@RequestMapping(value = "/test/login", method = RequestMethod.GET )

If you want those two pieces of code to talk to one another, they need to be set to the same method. In this case, you want a POST for both, but it's worth learning the distinction between the two for the future.

Lastly, there's the issue of getting information from your inputs and into your ajax XMLHTTP object. To do this, you're going to want to set up onChange hooks on the inputs, and attach them to a handleChange function within the react component. Use this function to save the values to the component's state, and then later take the values out of state to apply to the xmlhttp.

A simple example of what I am describing;

render() {

    return (
            <div>
                <input type="text" name="login" onChange={this.handleChange}/>
                <button onClick={this.login.bind(this)}>Login</button>
            </div>
    );
}

handleChange(value) {
    this.setState({login: value});
}

login () {

    var xmlhttp = new XMLHttpRequest();   // new HttpRequest instance 
    xmlhttp.open("POST", "/test/login");
    xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
    xmlhttp.send(JSON.stringify({login: this.state.login}));
}
Community
  • 1
  • 1
Jake Haller-Roby
  • 6,335
  • 1
  • 18
  • 31
  • so I now get code 400 on spring app because String parameter login is not present; while my react.js app displays `Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 403.`. My understanding is that react sees spring but cannot post to it, while spring just cannot receive the login parameter. – Santa Clauze Sep 19 '16 at 13:52
  • What you're now facing is a CORS issues. By default, servers do not allow you to access them unless you are coming from something they created. This is good. You don't want someone else to write a program that allows them to send login requests to your system. However, it's an issue for you because your react and api components are hosted on different hosts (locahost:8080 vs localhost:9000). To fix this, you will need to tell your api to allow incoming requests from localhost:9000; `@CrossOrigin(origins = "http://localhost:9000")` – Jake Haller-Roby Sep 19 '16 at 16:28
  • I have actually overcome the issue via a CORSFilter that was submitted by someone (I also tried that option and for some reason went for the previous one). So, now when I submit from reactjs app I get error 400 (OK) in red, but that activates my console from the Spring application and triggers `Required String parameter 'login' is not present`. So I feel that now they are connected, but that either the info is not well sent via react or the reception from spring is not well coded. – Santa Clauze Sep 19 '16 at 16:45