1

I've been trying to create a login page but I'm getting this error called "TypeError: Failed to fetch". I have no idea where I did wrong, I checked a few StackOverflow answers, like I tried adding the event.preventdefault as I saw in one of StackOverflow answer but that didn't help.

Could someone point out the part where I'm doing wrong?

Also note: it's working fine in postman with the API. I tried the same email and password there and it's working fine in postman but getting the error with the react website.

import React, { Component } from "react";
class Login extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "",
      password: ""
    };
    this.onchange = this.onchange.bind(this);
  }

  onchange(e) {
    this.setState({ [e.target.name]: e.target.value });
    console.log(this.state);
  }

  performLogin = async event => {
    event.preventDefault();
    console.log("button clicked");
    var body = {
      password: "this.state.password",
      email: "this.state.email"
    };

    const options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      },
      body: JSON.stringify(body)
    };

    const url = "/api/authenticate";

    try {
      const response = await fetch(url, options);
      const result = await response.json();
      console.log(result);
      console.log(`login successful`);
      window.alert("login succesful");
    } catch (error) {
      console.error(error);
    }
  };

  render() {
    return (
      <div>
        <input type="text" placeholder="emailid" onChange={this.onchange} />
        <br />
        <input
          type="password"
          placeholder="Enter your Password"
          onChange={this.onchange}
        />
        <br />
        <button type="submit" onClick={event => this.performLogin(event)}>
          Submit
        </button>
      </div>
    );
  }
}
export default Login;

one anamoly is that in postman, it accepts only when I post like I've shown below

{
    "password":"pass",
    "email":"admin"
}

If I remove the quotes then it gives me bad string error in postman but in codesandbox, the quotes are automatically removed when I save the sandbox. could it be because of that or is it nothing to worry about?

2
  • Are you getting any more error message in console or any status code? The issue can be a CORS issue. Commented Dec 7, 2019 at 20:00
  • no, just typeError: Failed to fetch. Commented Dec 7, 2019 at 20:01

1 Answer 1

2

First you need to give your inputs name attribute to be able to correctly update the state onChange like this:

<input type="text" name="email" placeholder="emailid" onChange={this.onchange} /> <br />
<input type="password" name="password" placeholder="Enter your Password" onChange={this.onchange}/>

Secondly, you need to create the request body like this:

   var body = {
      password: this.state.password,
      email: this.state.email
    };

And lastly, you need to check if fetch response is ok, because in 4xx errors fetch does not give error.

So with all these changes, your component code must be like this:

import React, { Component } from "react";
class Login extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "",
      password: ""
    };
    this.onchange = this.onchange.bind(this);
  }
  onchange(e) {
    this.setState({ [e.target.name]: e.target.value });
  }
  performLogin = async event => {
    event.preventDefault();
    var body = {
      password: this.state.password,
      email: this.state.email
    };
    const options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      },
      body: JSON.stringify(body)
    };
    const url = "/api/authenticate";
    try {
      const response = await fetch(url, options);
      const result = await response.json();
      console.log(result);
      if (response.ok) {
        console.log("login successful");
        window.alert("login succesful");
      } else {
        console.log("login failed");
        window.alert("login failed");
      }
    } catch (error) {
      console.error(error);
    }
  };

  render() {
    return (
      <div>
        <input
          type="text"
          name="email"
          placeholder="emailid"
          onChange={this.onchange}
        />
        <br />
        <input
          type="password"
          name="password"
          placeholder="Enter your Password"
          onChange={this.onchange}
        />
        <br />
        <button type="submit" onClick={event => this.performLogin(event)}>
          Submit
        </button>
        <hr />
        State: {JSON.stringify(this.state)}
      </div>
    );
  }
}
export default Login;

But these fixes in react app will not be enough, because codesandbox uses https and login api is using http. This will give the following error:

Mixed Content: The page at 'https://hkj22.csb.app/Login' was loaded over HTTPS, but requested an insecure resource 'http://***/api/authenticate'. This request has been blocked; the content must be served over HTTPS.

And only way to resolve this problem seems to use https for the api as described in this answer.

You can contact api owner to host his api using https.

Sign up to request clarification or add additional context in comments.

8 Comments

I'm still getting the same error TypeError: Failed to fetch with your updated code.
@UbuntuNewb then you have additionally cors issues. After you enable cors in your api, this code will work.
@UbuntuNewb did you enabled cors in your api?
i don't do the backend. there's a backend guy for this work. how do I know there is a cors issue before I direct the issue to him?
@UbuntuNewb check your browser console if there seems any error.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.