1

In my application, a token is used to retrieve user's data with a function. Here's it:

export function getUserInfos(token) {
    if (token == "") {
        window.location = "/";
    }
    axios.get(
        url,
        {
            headers: {
                "Authorization": "Bearer " + token
            }
        }
    ).then((result) => {
        var surname = result.data.userInfos.surname;
        var name = result.data.userInfos.name;
        var userInfos = {
            surname: surname,
            name: name
        }
        document.title = "Profil - " + surname + " " + name;
        console.log(userInfos)
        return userInfos;
    }).catch((err) => {
    })
}

console.log(userInfos) works fine when the function is called but impossible to get this value with setState(), in the side of my component. Whatever I do I'm still getting undefined. Here's the code in my component:

class HomePage extends Component {
    static propTypes = {
        cookies: instanceOf(Cookies).isRequired
    };

    constructor(props) {
        super(props);

        const { cookies } = props;
        this.state = {
            token: cookies.get('token')
        }
    };
    componentDidMount() {
        this.setState((state, props) => {
            return {userInfos: getUserInfos(this.state.token)}
        }, () => {
            console.log(this.state.userInfos) // 'undefined'
        })
    }

    render() {
        console.log(this.state)
        return (
            <div>
                <h1>MyHomePage</h1>
            </div>
        )
    }
}

export default withCookies(HomePage);

I'm sure this is a problem with asynchronous functions but I can't surround where the problem is from or what I'm doing wrong. I also checked and this is not a problem with the importation of my function getUserInfos.

palmtreesnative
  • 2,835
  • 3
  • 14
  • 22
  • Try : `async componentDidMount() { let user = await getUserInfos(this.state.token) this.setState({ userInfos: user }) }` – Steve Nov 10 '18 at 18:36
  • 1
    Your `getUserInfos` function doesn't have `return xyz` anywhere (one of the axios callback functions does, but not `getUserInfos`). So calling it results in `undefined`. See the linked question, but in short: You need to: 1. Return the promise from `getUserInfos`, 2. Remove the error suppressor in `getUserInfos` and allow errors to propagate to the caller, 3. Use the promise it returns when calling it, and only set state when the promise settles (setting `userInfos` when it resolves, setting an error condition for display when it rejects). – T.J. Crowder Nov 10 '18 at 18:36
  • @SteveNosse - Only if you have a `try`/`catch` around the whole thing. React doesn't consume the promise that would make `componentDidMount` produce, so errors won't be handled. – T.J. Crowder Nov 10 '18 at 18:37
  • I never really touched to Promises but it solved my problem. Thank you! – palmtreesnative Nov 10 '18 at 19:10

1 Answers1

0

You need to use api call inside componentDidMount another way. Set state only after promise resolves.

componentDidMount() {
    getUserInfos(this.state.token).then((userInfos) => {
      this.setState({userInfos: userInfos})
    })
}
Kort
  • 420
  • 3
  • 10
  • 1
    `getUserInfos` will need to be edited to return the promise as well. Also, you can replace `{userInfos: userInfos}` with just `{userInfos}`. (But this is an often-asked duplicate with a robust dupetarget.) – T.J. Crowder Nov 10 '18 at 18:34
  • @T.J.Crowderyou can use whatever syntax ES6, or ES5. It's just a syntax, it's doesn't matter. `getUserInfos` currently returns a promise with `return`. – Kort Nov 10 '18 at 18:36
  • 1
    I suggest you look again. It doesn't. (And since you're already using ES2015+ syntax, I just thought I'd point out you could make it more concise.) – T.J. Crowder Nov 10 '18 at 18:38
  • ok, got it. Just need to be added `return` before axios call. – Kort Nov 10 '18 at 18:38