gnzg
gnzg

Reputation: 370

React: Wait until all assets are loaded

In a React.js project, I'm fetching svgs inside of the componentWillMount() lifecycle method via a function called loadAllAssets(). These are then saved inside of the user's localStorage.

(1) Is there a more elegant way of checking whether all requested svg files have been indeed saved inside localStorage other than iterating over the number of requests made and comparing them to the content of localStorage?

(2) Is there a nicer way to prevent the initialization of componentDidMount as long as resources are still loading other than wrapping the entire code in a conditional? I am using Redux so that would come to mind as well but seems to me like using a sledgehammer to crack a nut.

index.js

import { loadAllAssets } from './utils/loadAllAssets';

class AppContainer extends React.Component {
  componentWillMount() {
    loadAllAssets();
  }
//...
}
ReactDOM.render(<Provider store={store} ><AppContainer /></Provider>, 
document.getElementById('root'));

loadAllAssets.js

import { ajaxSVG } from './gfAssetsLoader';

export const loadAllAssets = () => {
  /* write to localStorage */
  ajaxSVG('closeScene', '/assets/svg/close-scene-ani.svg');
//...
}

gfAssetsLoader.js

export const ajaxSVG = (assetName, path) => {
  try {
    let request = new XMLHttpRequest();
    request.open("GET", path, true);
    request.onload = function (e) {
      if( request.status >= 200 && request.status < 400 ) {
        let data = request.responseText;
        localStorage.setItem(assetName, data);
      } else console.log('Bad request. request status: ' + request.status);
    }
    request.send();
  }
  catch (e) {
    console.log(e);
  }
};

Upvotes: 7

Views: 12269

Answers (1)

Jesus Mendoza
Jesus Mendoza

Reputation: 323

1-

export const loadAllAssets = () => {
  /* write to localStorage */
  return ajaxSVG('closeScene', '/assets/svg/close-scene-ani.svg');
  //...
}

export const ajaxSVG = (assetName, path) => {
  return new Promise((resolve, reject) => {
    try {
      let request = new XMLHttpRequest();
      request.open("GET", path, true);
      request.onload = function (e) {
        if( request.status >= 200 && request.status < 400 ) {
          let data = request.responseText;
          localStorage.setItem(assetName, data);
          resolve();
        } else reject('Bad request. request status: ' + request.status);
      }
      request.send();
    }
    catch (e) {
      reject(e);
    }
  });
};

Now you can concatenate a .then to loadAllAssets() and change the state there.

2- To show the a loading state just create a state of loading and change it to false when the data loaded, so it will show a loader while the data is loading and after it's done it will show the data.

import { loadAllAssets } from './utils/loadAllAssets';

class AppContainer extends React.Component {
  constructor() {
    super();

    this.state = {
       loading: false
    };
  }

  componentWillMount() {
    loadAllAssets()
    .then(() => {
      this.setState({ loading: false });
    });
  }
//...
  render() {
    if (this.state.loading) {
       return (
         <div><h1>Loading...</h1></div>
       );
    }

    return (
       //...something else
    );
  }
}
ReactDOM.render(<Provider store={store} ><AppContainer /></Provider>, 
document.getElementById('root'));

Upvotes: 4

Related Questions