2

I'm trying to implement react-ga but only in production server (I have my local / dev and prod servers).

So, I would like to create a text field in backoffice which value is saved in database.

Then in the front side, I initialize react-ga only if I have a value in database.

To achieve this, I'm trying do this in componentDidUpdate in App.jsx.

I retrieve all my data set in backoffice via :

componentDidMount() {
    // I get my data in this.props.data_admin
    this.props.list_admin();
}

Then in componentDidUpdate(prevProps, prevState) I check if this.props.data_admin is set and not null, and when I got values I would like to initialize react-ga :

componentDidUpdate(prevProps, prevState, snapshot) {
    if (this.props.data_admin) {
        // this.props.data_admin.trackingNumber = UA-XXXXXXXXX
        ReactGA.initialize(this.props.data_admin.trackingNumber);
    }
}

But this gonna be done a lot of times (each time App.jsx is updated). So I should check before initialize if it's already done. How can I check if react-ga is already initialized ?

Thanks for your help

Alexis
  • 347
  • 5
  • 16

3 Answers3

1

I think you should not be doing this in componentDidUpdate but in componentDidMount after you have retrieved your data.

Your data retrieval process is an asynchronous call to your backend/database, it should return a Promise that resolves with the data retrieved. You can then initialize react-ga.

componentDidMount() {
    // I am assuming this.props.list_admin() returns your data
    this.props.list_admin().then((data_admin) => {
      if (data_admin) {
        // data_admin.trackingNumber = UA-XXXXXXXXX
        ReactGA.initialize(data_admin.trackingNumber);
      }
    });
}
  • That would be nice ! But this action calls a Symfony route which returns a JsonResponse, not a Promise... response example : `$arrayToSend = [ 'fontColor' => '#ffffff', 'backgroundColorFirst' => '#ffffff', 'backgroundColorSecond' => '#000000', 'backgroundColorMenu' => '#000000', 'buttonColor' => '#E5973E', 'buttonFontColor' => '#ffffff', ];` – Alexis May 27 '19 at 14:14
  • Your async call to the Symfony route returns a promise actually. Whether you are using JS fetch or JS ajax or jquery ajax or any call library, they usually provide asynchronous implementations. If your call is synchronous though, make the call, save the response and then initialize react-ga all in componentDidMount – Chukwuemeka Onyenezido May 27 '19 at 15:16
  • I'm trying to do a .then on it but I got an error like : this.props.data_admin.then is not a function. data_admin contains data (object with data like an array) called with this.props.list_admin() in mapDispatchToProps. And if I try to do this in componentDidMount() data_admin is null when he goes through function. In componentDidUpdate I could check if data_admin is not null – Alexis May 29 '19 at 10:05
  • Okay so `data_admin` is null in `componentDidMount()`? A call to `this.props.list_admin()` would populate `data_admin` with data via `mapDispatchToProps` and then call `componentDidUpdate` with the new props, correct? If that is the case I suggest moving `data_admin` to state, not props and calling `this.props.list_admin()` in your constructor and updating `data_admin` in state with it. Then in `componentDidMount()`, `data_admin` will already have a value and you can initialize react-ga – Chukwuemeka Onyenezido May 29 '19 at 11:30
  • I tried to call `this.props.list_admin()` from `componentDidMount` and then `console.log(this.props.data_admin)` in `componentDidUpdate`. Each time it is logged, data_admin got the Object with data. What do you mean with "moving data_admin to state" / "updating data_admin in state" ? (I'm new in React) – Alexis May 29 '19 at 11:48
  • In your class `constructor`, call `this.props.list_admin()` and then try checking checking the value of `data_admin` in `componentDidMount` – Chukwuemeka Onyenezido May 29 '19 at 11:54
  • I call `this.props.list_admin()` in constructor. Then in `componentDidMount` I did `console.log(this.props.data_admin);` the object is empty (`data_admin` still is in `mapStateToProps`) – Alexis May 29 '19 at 12:05
0

Finally what I did :

I called this.props.list_admin(); in App.jsx constructor and I created a state variable initialized at false :

constructor(props) {
    super(props);

    this.state = {
        googleAnalyticsInitialized: false,
    };

    this.props.list_admin();
}

Then, in componentDidupdate I checked values from this.props.data_admin and if googleAnalyticsInitialized is false. If it is, I initialiaze Google Analytics with the ID received from the call to the API :

componentDidUpdate(prevProps, prevState, snapshot) {
    if (this.props.data_admin && this.props.data_admin.idGoogleAnalytics && !this.state.googleAnalyticsInitialized) {
        ReactGA.initialize(this.props.data_admin.idGoogleAnalytics);
        this.setState({googleAnalyticsInitialized: true});
    }
}

Thanks to @Chukwuemeka Onyenezido who helped me and directed me on the right way.

Alexis
  • 347
  • 5
  • 16
0

I was hoping to find a better answer than this, but I simply did

try {
    console.log(theObject);
} catch(e) {}

Not very elegant, a bit dirty, I'd like to understand more about what is going on, but this works.

Back Story

I'm trying to access the store in a reducer and importing the store object from the index.js is my current "solution"

Jacksonkr
  • 31,583
  • 39
  • 180
  • 284