1

I'm creating a React component that will be displayed on the landing page. The component will display a string from the back office. If the string contains a specific chain, like #age#, this would trigger an ajax request to get the user's age, and then replace #age# by it.

My issue is that even though I can access my string, and it works with a string I created myself for some tests, it doesn't work when I work with this.state, saying it's undefined. I also can't make it work with any function whatsoever.

Here is how I do this so far:

import React from 'react';

export default class homeLanding extends React.Component {

    state = {
        settings_data: [],
        user_data: [],
    };

    componentDidMount() {
        if(localStorage.getItem('settings_data') === null) {
            $.ajax({
                url: '/settings',
                method: 'GET',
                dataType: 'json',
                success: function(data){
                    self.setState({settings_data: data});
                    localStorage.setItem('settings_data', JSON.stringify(data));
                }
            });
        }
        else {
            this.setState({settings_data: JSON.parse(localStorage.getItem('settings_data'))});
        }

    }

    render() {

        let welcome_title = this.state.settings_data.welcome_title; 
        // returns "welcome to site"

        if(welcome_title.includes('site')) {
            console.log('yaaaaaaay');
        } // error, cannot read includes of undefined
 return (
            <div className="col-md-10 main">
                <h1>{this.state.settings_data.welcome_title}</h1>
                <!-- Displays correctly the title -->
            </div>
        )
    }
}

My question is the following: why doesn't it work, and how can I make it so? Am I missing anything?

Jaeger
  • 1,686
  • 1
  • 30
  • 50
  • Have you tried to set the state in the constructor instead of using props initialisers? – Kev Jul 21 '17 at 08:18
  • 1
    Also your settings_data in an array and you are trying to access a property called welcome_title on it, that is undefined. – Kev Jul 21 '17 at 08:21

2 Answers2

2

Ajax is asynchronous. Although you're starting your ajax call in componentDidMount (well, maybe; more on that in a minute), it doesn't finish then. It finishes later.

So if componentDidMount starts the call (in the case where you don't have settings in local storage yet) and then render is called, you're trying to use this.state.settings_data.welcome_title when this.state.settings_data is still its initial value, [], which doesn't have welcome_title.

render should handle the case where you don't have the data yet, and then the case where you do, e.g.:

if (typeof welcome_title === "undefined") { // Or your favorite way of checking
    // ...you don't have it yet...
} else {
    // ...you have it and it isn't blank...
}

Separately: You're using self in the ajax callback in componentDidMount, but not setting it anywhere. That isn't why you're getting the error you're getting, but it could be why you'll get your next error (that you can't call setState).

You could use an arrow function and this instead:

componentDidMount() {
    if(localStorage.getItem('settings_data') === null) {
        $.ajax({
            url: '/settings',
            method: 'GET',
            dataType: 'json',
            success: data => {                                               // ***
                this.setState({settings_data: data});                        // ***
                localStorage.setItem('settings_data', JSON.stringify(data));
            }
        });
    }
    else {
        this.setState({settings_data: JSON.parse(localStorage.getItem('settings_data'))});
    }
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thank you a lot, all of you guys made me understand more about asynchronous, I thought that since I make a call on a local server, the ajax request won't take any time to be done. Well it doesn't, make it still is longer than the page loading. – Jaeger Jul 21 '17 at 08:31
-1

jquery is not definied

npm install jquery

import {$,jQuery} from 'jquery'; window.$ = $; window.jQuery = jQuery;

then use

$.ajax({ url: '/settings', method: 'GET', dataType: 'json', success: function(data){ self.setState({settings_data: data}); localStorage.setItem('settings_data', JSON.stringify(data)); } });

you can use or use https://www.npmjs.com/package/axios

  • As you can see I put my ajax in my localStorage so I don't make 458493 ajax call when I reload the page. So actually, thank you for making me notice but it didn't solve my problem – Jaeger Jul 21 '17 at 08:23