hcmc AccountList 백엔드 작성

세인트킴·2024년 5월 19일

hcmc

목록 보기
2/10
const columns = [
  { id: "date", label: "Category", minWidth: 110 },
  { id: "title", label: "Title", minWidth: 110 },
  { id: "category", label: "Category", minWidth: 120 },
  { id: "amount", label: "Amount", minWidth: 100, align: "right" },
];

컬럼을 미리 정해줘서, 입력한 데이터가 어떤 key: value형식으로 들어가는지 정해준다.

const AccountList = (props) => {
  const { totalIncome, totalExpense, monthFilter, tagFilter } = props;
  const [ rows, setRows ] = useState([]);
  const [ page, setPage ] = useState(0);
  const [ rowsPerPage, setRowsPerPage ] = useState(10);
  let [ expense, setExpense ] = useState(0);
  let [ income, setIncome ] = useState(0);
  
  ...중략
}

상태관리를 위해 useState()를 사용하는데, 컴포넌트 데이터와 UI를 동기화 하기 위해 사용한다. 상태가 변경되면 다시 렌더링 해서, 최신 데이터를 반영해준다. useState()를 사용할 때, 초기값을 넣지 않으면 undefined로 나온다.

const formatDate = (format) => {
  const options = { year: "numeric", month: "2-digit", day: "2-digit" };
  const date = new Date();
  return Intl.DateTimeFormat("en-CA", options).format(date);
}

useEffect(() => {
  const data = async() => {
    try {
      const response = await axios.get("http://localhost:4000/wallet/money");
      const formattedData = response.data.map((item) => ({
        ...item, date: formatDate(item.date)
      })))
      setRows(formattedData);
    } catch(err) {
      console.error(err);
    }
  }
  data();
}, []);

formatDate함수를 만들어서 format을 인자로 받고 year: 숫자, month, day는 2자리로 구성해서 "2024-05-19"같은 날짜 형식을 띄운다.

axios.get()요청을 보내줘서 MongoDB에 저장된 데이터를 item변수에 담아도록 한 뒤, map()함수를 통해 분리하고, 날짜 형식 date는 위에서 만든 formatDate(item.date)를 넣어서 가져와서 연동해주고, setRows()를 호출해서 상태를 업데이트 해준다.
그 후 data()를 호출해준다.

배열이 비어있으므로, useEffect()는 컴포넌트가 처음 실행될 때 배열 내부가 추가되고 변경되지 않는다.

useEffect(() => {
  let exp = 0;
  let inc = 0;
  rows.forEach((item) => {
    if (item.tag === "지출") {
      exp += parseInt(item.amount);
    else if (item.tag === "수입") {
      inc += parseInt(item.amount);
    }
  });
  setExpense(exp);
  setIncome(inc);
  totalExpense(exp);
  totalIncome(inc);
  }, [rows, totalExpense, totalIncome]);

useEffect()를 한번 더 사용해준다. 다시 설명하자면 useEffec()는 컴포넌트가 렌더링 될 때마다 함수 내부의 문장을 실행하는 Hook이라고 정의할 수 있다.
배열 안에 rows, totalExpense, totalIncome을 넣었으니 이 부분이 변경되면 다시 렌더링 되도록 한다.

rows의 tag가 지출이라면, exp에 값을 추가하고, 수입이라면 inc에 값을 추가해준다. 그리고 지출과 수입을 useState()에 업데이트 해준다.

const handleChangePage = (event, newPage) => {
  setpage(newPage);
};

const handleChangeRowsPerPage = (event) => {
  setRowsPerPage(+event.target.value);
  setPage(0);
};

페이지네이션을 위한 함수이다. handleChangePage는 사용자가 페이지를 변경할 때 호출된다. newPage를 호출해서 현재 페이지 상태를 newPage로 업데이트 해준다.

handleChangeRowsPerPagesetRowsPerPage를 호출해서 페이지 당 표시할 행 숫자를 업데이트 해준뒤, 현재 페이지를 0으로 리셋해준다.

<div className="AccountList">
      <TableContainer sx={{ maxHeight: 440 }}>
        <Typography sx={{ flex: "1 1 100%" }} id="tableTitle" component="div">
          <Tooltip title="Filter list">
            <IconButton>
              <FilterListIcon type="button" onClick={tagFilter} />
            </IconButton>
          </Tooltip>

          <select
            className="monthFilter"
            placeholder="월"
            onChange={monthFilter}
            required
            defaultValue=""
          >
            <option value="" disabled>
              월별 필터
            </option>
            <option value="01">1</option>
            <option value="02">2</option>
            <option value="03">3</option>
            <option value="04">4</option>
            <option value="05">5</option>
            <option value="06">6</option>
            <option value="07">7</option>
            <option value="08">8</option>
            <option value="09">9</option>
            <option value="10">10</option>
            <option value="11">11</option>
            <option value="12">12</option>
          </select>
        </Typography>

        <Table stickyHeader aria-label="sticky table">
          <TableHead>
            <TableRow>
              {columns.map((column) => (
                <TableCell
                  key={column.id}
                  align={column.align}
                  style={{ minWidth: column.minWidth }}
                >
                  {column.label}
                </TableCell>
              ))}
            </TableRow>
          </TableHead>
          <TableBody>
            {rows
              .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
              .map((row) => {
                return (
                  <TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
                    {columns.map((column) => {
                      const value = row[column.id];
                      return (
                        <TableCell key={column.id} align={column.align}>
                          {value}
                        </TableCell>
                      );
                    })}
                  </TableRow>
                );
              })}
          </TableBody>
        </Table>
      </TableContainer>
      <TablePagination
        rowsPerPageOptions={[10, 25, 100]}
        component="div"
        count={rows.length}
        rowsPerPage={rowsPerPage}
        page={page}
        onPageChange={handleChangePage}
        onRowsPerPageChange={handleChangeRowsPerPage}
      />
    </div>
  );
profile
잘하는 건 노력

0개의 댓글