모달창 구현

세인트킴·2024년 5월 23일

hcmc

목록 보기
6/10
import { Box, Button, Modal } from '@mui/material';

기존의 @mui/material에서 Box, Button, Modal을 추가로 불러왔다.


// 모달창 스타일
const style = {
  position: "absolute",
  top: "50%",
  left: "50%",
  transform: "translate(-50%, -50%)",
  width: 400,
  bgcolor: "background.paper",
  border: "2px solid #000",
  boxShadow: 24,
  p: 4,
};

이거를 AccountList.js 파일에서 작성했는데, 다른 파일로 넘겨서 작성해야 할 것 같다. 현재는 임시방편으로 여기에 구현했다..

const [open, setOpen] = useState(false);
const [selectedRow, SetSelectedRow] = useState(null);

const handleOpen = (row) => {
  selectedRow(row);
  setOpen(true);
};

const handleClose = (row) => {
  setOpen(false);
  setSelectedRow(null);
};

const handleInputChange = (e) => {
  const { name, value } = e.target;
  setSelectedRow((prevRow) => ({ ...prevRow, [name]: value }));
};

useState()를 사용해서 모달창이 열려있는지, 닫혀있는지 구현할 수 있다. 기본적으로 false를 적용해주고 모달창이 열릴 때마다 true로 바꿔준다.

행을 클릭하면 데이터가 들어갈 수 있도록 selectedRowuseState(null)로 기본적으로 아무 값도 나오지 않게 만들어준다.

handleInputChange를 만들어서 모달창이 열리면 값의 변화를 알려주도록 만들어준다. 클릭한 데이터의 name, value를 setSelectedRow에 반영하도록 했다. ...prevRow는 prevRow 객체의 모든 속성을 복사해서 prev(이전)값을 [name]: value로 새롭게 설정해서 값을 업데이트 해준다.

// 모달창 리스트 데이터 수정
const handleSave = async () => {
  try {
  	const response = await axios.post(`http://localhost:4000/wallet/money/update/${selectedRow._id}`, selectedRow);
    setRows(updatedRows);
    handleClose();
    console.log(response.data);
  } catch(err) {
  	console.error(err);
  }
};

모달창에서 데이터를 수정하고, 선택한 데이터의 ObjectId를 백엔드 라우터로 모달창에서 데이터를 수정한 selectedRow객체를 같이 전송한다.

그 후, rows에서 반복문을 돌려서 row._idselectedRow._id가 일치하면 selectedRow를 리턴해서 해당 행을 selectedRow로 바꾸고, 아니면 row를 리턴한다.
그리고 setRows(updatedRows) 훅을 호출해서 바뀐 값을 업데이트 해준다.

모달창을 나가면 handleClose()를 호출해서 모달창을 닫아주고, 선택한 행도 null로 바꿔준다. 그 후 window.location.reload()를 해준다.

const handleDelete = async () => {
  try {
  	const response = await axios.post(`http://localhost:4000/wallet/delete/${selectedRow._id}`, selectedRow);
    handleClose();
    console.log(response.data);
  } catch(err) {
    console.error(err);
  }
}

모달창에 있는 버튼 중 하나인 delete버튼을 누르면 백엔드로 전송되는 로직이다. selectedRow를 객체로 백엔드로 보낸 뒤, handleClose()를 호출해서 모달창을 닫고, 보낸 데이터를 출력한다.

페이지네이션 로직

rows.slice((page && page >= 0 ? page : 0) * (rowsPerPage && rowsPerPage > 0 ? rowsPerPage : 10), (page && page >= 0 ? page : 0) * (rowsPerPage && rowsPerPage > 0 ? rowsPerPage : 10) + (rowsPerPage && rowsPerPage > 0 ? rowsPerPage : 10)

이거는 page가 0보다 크면 page를 리턴하고, 아니면 0을 리턴한 값을 rowsPerPage도 같은 로직을 곱한 값을 시작 인덱스로 정하고, 끝 인덱스는 시작 인덱스 값에 rowsPerPage를 더해준 것을 끝 인덱스로 해주는 로직이다. 이렇게 추가한 이유는 .slice를 읽을 수 없다는 에러메세지가 나오기 때문에 이 로직을 추가했다.

원래는 모달창에서 category부분이 TextField로 되어있어서 원하는 대로 카테고리 수정이 안되는 버그가 생겼다. 이를 해결하기 위해 Mui/Material에서 제공하는 <Select> 태그와 그 안에 <option>을 대체할 <MenuItem> 태그를 사용해서 옵션 태그를 구현했다.

<Modal open={open} onClose={handleClose} aria-labelledby="modal=modal-title" aria-describedby="modal-modal-description">
  <Box sx={{ ...style, width: 400 }}>
  	<Typography id="modal-modal-title" variant="h6" component="h2">
  	  <FormLabel>
  	  	<TextField margin="normal" fullWidth type="date" name="date" value={selectedRow.date} onChange={handleInputChange}/>
  		  <Select margin="normal" fullWidth name="category" value={selectedRow.category} onChange={handleInputChange}>
  			<MenuItem disabled>지출</MenuItem>
  			<MenuItem value="식비">식비</MenuItem>
  			<MenuItem value="생필품">생필품</MenuItem>
  			<MenuItem value="문화/교육비">문화/교육비</MenuItem>
  			<MenuItem value="기타">기타</MenuItem>
  			<MenuItem value="저축">저축</MenuItem>
  			<MenuItem value="수입">수입</MenuItem>
  			<MenuItem value="월급">월급</MenuItem>
  			<MenuItem value="기타소득">기타소득</MenuItem>
		  </Select> 
		  <TextField margin="normal" fullWidth type="text" name="title" value={selectedRow.title} onChange={handleInputChange}/>
          <TextField margin="normal" fullWidth name="amount" value={selectedRow.amount} onChange={handleInputChange}/>
        <Button onClick={handleSave}>Save</Button>
        <Button onClick={handleDelete}>Delete</Button>
  	  </FormLabel>
	}}
  </Box>
</Modal>

open={open}을 클릭하면, 테이블이 클릭할 때, useState()에서 적은 open이 실행되서 모달창이 열린다.

variant="h6"는 텍스트 사이즈를 h6으로 변경하고, component="h2"Typography를 기본적으로 <span>태그로 인식하는데 이걸 h2로 바꿔서 렌더링 하게 해준다.

원래는 모달창의 category<TextField>였는데, 이걸 <Select>로 바꾸고, <Option>태그 대신 <MenuItem>으로 변경했다.

profile
잘하는 건 노력

0개의 댓글