How can I wait for init config to complete?

Viewed 952

I've this code

class ConnectedApp extends Component {

  constructor(props) {
    super();
    props.initConfig(); // the ajax call that populate the user settings
  }

  render() {

    return (
      <I18nextProvider i18n={i18n}>
        <Router>
          <div className="App" style={appStyle}>
            <Head/>
            <div className="Container">
              <Container/>
            </div>
            <Foot/>
            <Loading/>
            <ToastContainer position="bottom-right" />
          </div>
        </Router>
      </I18nextProvider>
    );
  }
}

Now the problem is that the initconfig is an ajax function in middleware. Before rendering the app for logged user I need to wait that the function has finished. Anyone have some suggestion?

Actually the app works nut on first login give an error and that error is resolved by manual refresh.

1 Answers

You'll need to change a few things here– Firstly you will need some way to indicate loading. This can be done in it's simplest form using a boolean either in your global or local state. You should also move your AJAX call method into the appropriate component lifecycle method componentDidMount.

You want it in your componentDidMount to ensure the component is mounted and ready to receive props or state changes.

class ConnectedApp extends Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    this.props.initConfig();
  }

  render() {
    if (this.props.loading === true) {
      return null // this will render nothing until loading is `false`
    }

    return (
      <I18nextProvider i18n={i18n}>
        <Router>
          <div className="App" style={appStyle}>
            <Head/>
            <div className="Container">
              <Container/>
            </div>
            <Foot/>
            <Loading/>
            <ToastContainer position="bottom-right" />
          </div>
        </Router>
      </I18nextProvider>
    );
  }
}

In your redux state you would want to set a property for the loading state. When you start the request, you would set loading to true, when it is successful set it to false. If it fails, you would need a more expandable solution to account for that other than a simple 'loading' boolean.

Also, if you haven't checked out the new React Hooks API, this is what your component would look like using that.

import React, { useEffect } from "react";

const ConnectedApp = ({ initConfig, loading }) => {
  useEffect(() => {
    initConfig() // this will only get called when the component mounts. Same as `componentDidMount`
  }, [])

  if (loading === true) {
    return null // this will render nothing until loading is `false`
  }

  return (
    <I18nextProvider i18n={i18n}>
      <Router>
        <div className="App" style={appStyle}>
          <Head/>
          <div className="Container">
            <Container/>
          </div>
          <Foot/>
          <Loading/>
          <ToastContainer position="bottom-right" />
        </div>
      </Router>
    </I18nextProvider>
  );
}
Related