본문 바로가기
개발/React

React Material - 비동기 함수 로딩 중 보여주기 (Mui Loading CircularProgress with Async Function)

by 피로물든딸기 2023. 7. 9.
반응형

리액트 전체 링크

 

참고

- 파일 브라우저에서 파일 다운로드하기

- 파일 다운로드 경과 확인하기

- 파일 다운로드 경과 로딩 과정 보여주기

 

3초 뒤에 끝나는 비동기 함수가 있다.

이 함수가 시작되고 끝나기까지 로딩 중이라는 표시를 만들어보자.

  function asyncFunction() {
    return new Promise(function (resolve, reject) {
      setTimeout(function () {
        resolve();
      }, 3000);
    });
  }

 

먼저 Mui의 모달을 추가한다.

import React, { useState } from "react";

import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Modal from "@mui/material/Modal";
import CircularProgress from "@mui/material/CircularProgress";

const LoadingBar = () => {
  const [open, setOpen] = useState(false);

  const style = {
    position: "absolute",
    top: "50%",
    left: "50%",
    transform: "translate(-50%, -50%)",
    width: "100%",
    height: "100%",
    bgcolor: "rgba(255,255,255,0.5)",
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
  };

  return (
    <div>
      <Modal
        open={open}
        aria-labelledby="modal-modal-title"
        aria-describedby="modal-modal-description"
      >
        <Box sx={style}>
          <CircularProgress />
        </Box>
      </Modal>
    </div>
  );
};

export default LoadingBar;

 

모달은 opentrueModal이 나타나고, false면 사라진다.

따라서 비동기 함수가 실행되기 전에 opentrue로, 비동기 함수가 종료되면 false로 변경하는 함수를 만든다.

이 함수를 test에 구현하고, Button을 만들어 onClick에 연결하자.

  const test = () => {
    setOpen(true);
    asyncFunction().then(() => setOpen(false));
  };

  return (
    <div>
      <Button variant="outlined" onClick={test}>Async function</Button>
      <Modal>
      ...
      </Modal>
    </div>
  );

 

버튼을 클릭하면 3초 동안 Loading 되는 것을 알 수 있다.

 

전체 코드는 다음과 같다.

import React, { useState } from "react";

import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Modal from "@mui/material/Modal";
import CircularProgress from "@mui/material/CircularProgress";

const LoadingBar = () => {
  const [open, setOpen] = useState(false);

  const style = {
    position: "absolute",
    top: "50%",
    left: "50%",
    transform: "translate(-50%, -50%)",
    width: "100%",
    height: "100%",
    bgcolor: "rgba(255,255,255,0.5)",
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
  };

  function asyncFunction() {
    return new Promise(function (resolve, reject) {
      setTimeout(function () {
        resolve();
      }, 3000);
    });
  }

  const test = () => {
    setOpen(true);
    asyncFunction().then(() => setOpen(false));
  };

  return (
    <div>
      <Button variant="outlined" onClick={test}>Async function</Button>
      <Modal
        open={open}
        aria-labelledby="modal-modal-title"
        aria-describedby="modal-modal-description"
      >
        <Box sx={style}>
          <CircularProgress />
        </Box>
      </Modal>
    </div>
  );
};

export default LoadingBar;

 

결과는 링크에서 확인하자.

 

만약 파일 다운로드에 대해서 적용하면 finally에서 open을 false로 변경하면 된다.

const download = (pathInfo) => {
  ...
  let server = `http://192.168.55.120:3002`;
  axios
    .get(`${server}/downloadFile?filePath=${pathInfo}`, {
      responseType: "arraybuffer",
    })
    .then((res) => {
      downloadPC(res, fileName);
    })
    .catch((error) => console.log(error));
    .finally(() => setOpen(false)); // loading 종료
};
반응형

댓글