1

I have the following component class:

import React, { Component } from "react";
import Form from "react-bootstrap/Form";
import Button from 'react-bootstrap/Button'
import './login.css';

export default class Login extends Component {

    handleSubmit = (e) => {

        var myRes = null;

        fetch(
            "/exist/apps/my-app/modules/who-am-i.xq?user=emh&password=emh",
            {
            }
        )
          .then((response) => response.json())
          .then(
            (result) => {
                myRes = {
                    error: null,
                    loaded: true,
                    user: result
                };
            },
            // Note: it's important to handle errors here
            // instead of a catch() block so that we don't swallow
            // exceptions from actual bugs in components.
            (error) => {
                myRes = {
                    error: error,
                    loaded: true,
                    user: {}
                };
            }
          );
        this.setState(myRes);
    }

    render() {
        return (
      <div className="auth-wrapper">
        <div className="auth-inner">
            <Form onSubmit={this.handleSubmit}>
                <h3>Sign In</h3>
.
.
.
                <Button variant="primary" type="submit">Submit</Button>
            </Form>
            </div>
            </div>
        );
    }
}

I have searched for the answer, but what I got was in (result) => {this.setState({error: null, loaded: true, user: result})}. Unfortunately the this is undefined within the fetch.

I want to in the result and error to set the value in state. Unfortunately the this is not defined within the fetch result. How do I set the state in Login from within the fetch?

2
  • 1
    Seems like you are setting the state without awaiting the resolution of the promise, so you will always set state to null Commented Aug 11, 2020 at 17:40
  • @thedude is correct. You're setting state outside the promise callback, which means it's probably running before the promise does. Commented Aug 11, 2020 at 17:44

3 Answers 3

1

The problem is you're calling setState too soon. You need to call it only when your promise has settled. The easiest way to do that is with a subsequent then, see *** comments:

handleSubmit = (e) => {
    // *** No `let myRes` here
    fetch(
         "/exist/apps/my-app/modules/who-am-i.xq?user=emh&password=emh",
         {
         }
     )
       .then((response) => response.json())
       .then(
         (result) => {
             // *** Transform the resolution value slightly
             return {
                 error: null,
                 loaded: true,
                 user: result
             };
         },
         // Note: it's important to handle errors here
         // instead of a catch() block so that we don't swallow
         // exceptions from actual bugs in components.
         (error) => {
             // *** Turn rejection into resolution by returning
             // a replacement for `myRes`.
             return {
                 error: error,
                 loaded: true,
                 user: {}
             };
         }
       )
       .then(myRes => {
         // *** You always end up here because both fulfillment and rejecction
         // result in an object that's used to fulfill the promise
         // created by the first call to `then`
         this.setState(myRes);
       })
       // *** Still use a final handler to catch errors from
       // fulfillment handlers
       .catch(error => {
         // Handle/report error
       });
};
Sign up to request clarification or add additional context in comments.

Comments

0

first of all fetch should always be async second put const that = this; in the top of the handler and then you can do setState like this:

handleSubmit = (e) => {
        const self = this
        var myRes = null;

        fetch(
            "/exist/apps/my-app/modules/who-am-i.xq?user=emh&password=emh",
            {
            }
        )
          .then((response) => response.json())
          .then(
           result => {
                self.setState({error: null, loaded: true, user: result})
                myRes = {
                    error: null,
                    loaded: true,
                    user: result
                };
            },
            // Note: it's important to handle errors here
            // instead of a catch() block so that we don't swallow
            // exceptions from actual bugs in components.
            (error) => {
                myRes = {
                    error: error,
                    loaded: true,
                    user: {}
                };
            }
          );
    }

and advise you to create a file for the fetch like this:

 const nameYouDecided = async () -> {
    await fetch("/exist/apps/my-app/modules/who-am-i.xq?user=emh&password=emh" )
          .then((response) => response.json())
    }

and then when you call it in your code it is shorter In addition if you have a couple of get request you should do the following in different file like get.js

    const get = async (url) => (
        await fetch(url)
            .then(response => response.json())
            .then(json => json
            )
    );
const nameYouDecided = get("/exist/apps/my-app/modules/who-am-i.xq?user=emh&password=emh")

Comments

0

You need to set the state inside of .then() fetch function.

Fetch need time to fetch urls, setstate doesnt wait this time so it set a Promise. To turn around this, you need to put your setState inside a .then, the setState line will only be executed when your fetch done the job

fetch(
  "/exist/apps/my-app/modules/who-am-i.xq?user=emh&password=emh",
  {
  }
)
.then((response) => response.json())
.then(
  (result) => {
      return {
          error: null,
          loaded: true,
          user: result
      };
  },

  (error) => {
      return {
          error: error,
          loaded: true,
          user: {}
      };
  }
).then(myRes => {
  this.setState(myRes); 
});
}

Comments

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.