admin管理员组

文章数量:1426620

When I navigate between pages in my React app, a see a bounce at each page (meaning that page is rendered first without any data [e.g. username, date of birth, images], then few milliseconds/seconds later some details appear on the screen as the API request has finished and updated the state.

For example I have the following pages:

<div className="home" onClick={() => history.push('/')}></div>
<div className="user" onClick={() => history.push('/user')}></div>
<div className="settings" onClick={() => history.push('/settings')}></div>

This results in behavior that when I click 'settings' button I first go to /settings route and then ponents starts rerendering and bouncing while making API requests. In each of these pages I make one or multiple API requests to get data. I make these requests using useEffect hook. For example:

const Settings = () => {
  const [userDetails, setUserDetails] = useState(null);
  const [userImages, setUserImages] = useState([]);

  useEffect(() => {
    const getUserDetails = async () => {
     const response = await getUserSettingsDetails();
     setUserDetails(response.data);
   }
   const getUserImages = async = () => {
     const response = await getUserSettingsImages();
     setUserImages(response.data);
  }
  getUserDetails();
  getUserImages();
  }, []);

  return ( 
     ... 
  );
}

What I want to achieve:

I want that when I am for example on 'homepage', and click to go to 'settings', to navigate and render Settings page only after the API requests finished and I can have all details on the screen immediately. I have a nice line loading ponent that I want to display in header while loading. (Similar to what YouTube has, it displays a red progress bar when navigating). I also use Redux for this project and I think it could be used here but I do not understand how to do this. Could anyone please explain how to achieve such behavior.

When I navigate between pages in my React app, a see a bounce at each page (meaning that page is rendered first without any data [e.g. username, date of birth, images], then few milliseconds/seconds later some details appear on the screen as the API request has finished and updated the state.

For example I have the following pages:

<div className="home" onClick={() => history.push('/')}></div>
<div className="user" onClick={() => history.push('/user')}></div>
<div className="settings" onClick={() => history.push('/settings')}></div>

This results in behavior that when I click 'settings' button I first go to /settings route and then ponents starts rerendering and bouncing while making API requests. In each of these pages I make one or multiple API requests to get data. I make these requests using useEffect hook. For example:

const Settings = () => {
  const [userDetails, setUserDetails] = useState(null);
  const [userImages, setUserImages] = useState([]);

  useEffect(() => {
    const getUserDetails = async () => {
     const response = await getUserSettingsDetails();
     setUserDetails(response.data);
   }
   const getUserImages = async = () => {
     const response = await getUserSettingsImages();
     setUserImages(response.data);
  }
  getUserDetails();
  getUserImages();
  }, []);

  return ( 
     ... 
  );
}

What I want to achieve:

I want that when I am for example on 'homepage', and click to go to 'settings', to navigate and render Settings page only after the API requests finished and I can have all details on the screen immediately. I have a nice line loading ponent that I want to display in header while loading. (Similar to what YouTube has, it displays a red progress bar when navigating). I also use Redux for this project and I think it could be used here but I do not understand how to do this. Could anyone please explain how to achieve such behavior.

Share Improve this question edited Apr 26, 2021 at 22:27 user12051965 asked Apr 26, 2021 at 22:18 user12051965user12051965 15712 silver badges39 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 2

You can create an extra state called isLoading and set it true when any fetch of data starts. Then, below the await statement, you can set isLoading to false.

So, with this, you can use the isLoading state in your JSX code, to make a conditional rendering, for example, you can display a Loading Component while the isLoading variable has the value of true, then, when the variable is false, display your page as you want.

const Settings = () => {
  const [state, setState] = useState({});
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    const getAllInformation = async () => {
      // start loading
      setIsLoading(true);
      // make the request here
      const data = await fetch();
      setState({ ...data });
      // already finished here
      setIsLoading(false);
    };
    getAllInformation()
  }, []);

  return (
    <div>
      {isLoading ? (
        <Loading />
      ) : (
        {
          /* MORE CODE */
        }
      )}
    </div>
  );
};

hi I think you can use Promise.all([]) and a loading state

const Settings = () => {
 const [userDetails, setUserDetails] = useState(null);
 const [userImages, setUserImages] = useState([]);
 const [loading,setLoading] = useState(false)

 const getUsersInfos = async () => {
  try {
   const result = await new Promise.all([
     getUserSettingsDetails(),
     getUserSettingsImages(),
   ])

   const details = result[0]
   const images = result[1]

   //i'm not sure if we need to test
   if(details.data && images.data){
     setUserDetails(details.data);
     setUserImages(images.data);
     setLoading(true)
   }

  } catch (error) {
   console.log(error);
 }
}

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

return ( 
  <>
   {loading && (
     ...
   )}
  </>
 );
}

Although I believe @Daphaz answer is pretty well, I'll go with a better and cleaner approach using redux-thunk or redux-sagas. With redux you can only do simple synchronous updates, and here you will be doing asynchronous updates hence you will need a middleware like those I mentioned.

Redux-thunk Redux-sagas

There are tons of examples of usings this middlewares to achieve exactly what you are looking for.

本文标签: javascriptReact render page after API callStack Overflow