Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disabling the preloader after the data appears on the website

How can I set the preloader in axios.interceptor to turn off how will the data be displayed on the page? At this point, I can see the data is downloaded, the preloader turn off and I can see the jump as the data appears on the page. Intended effect: disabling the preloader when data appears on the website.

Example: https://stackblitz.com/edit/react-ca6osn?file=src%2FApp.js

Axios.interceptors.request.use(function (config) {

  // spinning start to show
  // UPDATE: Add this code to show global loading indicator
  document.body.classList.add('loading-indicator');

  return config
}, function (error) {
  return Promise.reject(error);
});

Axios.interceptors.response.use(function (response) {

  // spinning hide
  // UPDATE: Add this code to hide global loading indicator
  document.body.classList.remove('loading-indicator');

  return response;
}, function (error) {
  return Promise.reject(error);
});

export default function App() {
  const [values, setValues] = useState({
        title: []
    });

  useEffect(() => {
    loadProfile();
    }, []);


    const loadProfile = () => { 

        axios({
            method: 'GET',
            url: `https://jsonplaceholder.typicode.com/todos`,
          })
          .then(res => {

        setValues({...values, title: res.data});
          })
          .catch(err => {
        console.log('error', err.response.data);
      
          })
  }

  return (
    
    <div>
       {values.title.map(data => (
          <div style={{ border: "1px black solid" }}>
            <p>{data.title}</p>
          </div>
      ))}
    </div>
  );
}

CSS

.loading-indicator:before {
    content: '';
    background: black;
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    z-index: 1000;
}

.loading-indicator:after {
    content: 'Loading';
    position: fixed;
    width: 100%;
    top: 50%;
    left: 0;
    z-index: 1001;
    color:white;
    text-align:center;
    font-weight:bold;
    font-size:1.5rem;        
}
like image 343
Umbro Avatar asked Oct 02 '20 18:10

Umbro


1 Answers

I'm not sure you can do it using the Axios.interceptors because there will always be a lag between the time the data received to the time the data gets render. However, I can suggest you check in the code if the data exists already and decide what to do depends on this. You can change the className of the outer div depending on your data.

It should be something like this:

export default function App() {
  const [values, setValues] = useState({
        title: []
    });

  useEffect(() => {
    loadProfile();
    }, []);


    const loadProfile = () => { 

        axios({
            method: 'GET',
            url: `https://jsonplaceholder.typicode.com/todos`,
          })
          .then(res => {

        setValues({...values, title: res.data});
          })
          .catch(err => {
        console.log('error', err.response.data);
      
          })
  }

  return (
    
    <div className={values?.title?.length ? null : "loading-indicator"}>
       {values.title.map(data => (
          <div style={{ border: "1px black solid" }}>
            <p>{data.title}</p>
          </div>
      ))}
    </div>
  );
}

If you are not sure if data will be received from the server you can also create a new boolean variable in the state which will change from false to true when you get a response from the Axios request and use it to change the className of the div.

like image 171
Ran Marciano Avatar answered Oct 27 '22 11:10

Ran Marciano