Update는 Create, Delete와는 조금 다릅니다. 수정은 두가지 경우가 있기 때문입니다.
① checkbox 수정
② title 수정
① checkbox 수정은 매우 간단합니다. 체크박스 클릭 시 item.done의 값을 변경하면 됩니다.
② title 수정이 약간 복잡한데요. 사용자가 title을 클릭하면 수정 가능한 상태
로 만들고, Enter
를 누르면 수정 내용을 저장하도록 하려고 합니다. 이를 위해 readOnly
가 필요합니다.
사용자는 readOnly
가 true인 경우 수정할 수 없고, false인 경우 수정할 수 있습니다.
① editItem 함수는 수정 후 새로운 배열을 생성하여 추가합니다.
import './App.css';
import Todo from './Todo';
import React, { useState } from 'react';
import { Container, List, Paper } from '@mui/material';
import AddTodo from './AddTodo';
function App() {
const [items, setItems] = useState([]);
const addItem = (item) => {
item.id = "ID-" + items.length;
item.done = false;
// 업데이트는 반드시 setItems로 하고 새 배열을 만들어야 한다.
setItems([...items, item]);
console.log("items : ", items);
}
const deleteItem = (item) => {
// 삭제할 아이템을 찾는다.
const newItems = items.filter(e => e.id !== item.id);
// 삭제할 아이템을 제외;한 아이템을 다시 배열에 저장한다.
setItems([...newItems])
}
const editItem = () => {
setItems([...items]);
}
let todoItems = items.length > 0 && (
<Paper style={{ margin: 16 }}>
<List>
{items.map((item) => (
<Todo item={item} key={item.id} editItem={editItem} deleteItem={deleteItem} />
))}
</List>
</Paper>
);
return <div className="App">
<Container maxWidth="md">
<AddTodo addItem={addItem} />
<div className="TodoList">{todoItems}</div>
</Container>
</div>
}
export default App;
① editItem은 상위 컴포넌트인 App에서 props.editItem
으로 함수를 불러옵니다.
② turnOnReadOnly는 사용자의 입력값(e)이 enter인 경우 ReadOnly 값을 true로 변경합니다.
③ editEventHandler는 사용자가 입력한 값(e.target.value)을 item.title
에 저장합니다.
import React, { useState } from 'react';
import {
ListItem,
ListItemText,
InputBase,
Checkbox,
ListItemSecondaryAction,
IconButton,
} from '@mui/material';
import DeleteOutlined from '@mui/icons-material/DeleteOutlined';
const Todo = (props) => {
const [item, setItem] = useState(props.item);
const [readOnly, setReadonly] = useState(true);
const deleteItem = props.deleteItem;
const editItem = props.editItem;
const turnOffReadOnly = () => {
setReadonly(false);
}
const turnOnReadOnly = (e) => {
if (e.key === 'Enter') {
setReadonly(true);
}
}
const editEventHandler = (e) => {
item.title = e.target.value;
editItem();
}
const checkboxEventHandler = (e) => {
item.done = e.target.checked;
editItem();
}
// deleteEventHandler 작성
const deleteEventHandler = () => {
deleteItem(item);
}
return (
<ListItem>
<Checkbox checked={item.done} onChange={checkboxEventHandler}/>
<ListItemText>
<InputBase
inputProps={{
"aria-label": "naked",
readOnly: readOnly
}}
onClick={turnOffReadOnly}
onKeyDown={turnOnReadOnly}
onChange={editEventHandler}
type="text"
id={item.id}
name={item.id}
value={item.title}
multiline={true}
fullWidth={true}
/>
</ListItemText>
<ListItemSecondaryAction>
<IconButton aria-label="Delete Todo" onClick={deleteEventHandler}>
<DeleteOutlined />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
)
}
export default Todo;
다음 글은 백엔드와 프론트엔드를 통합하는 방법에 대해 다룹니다.
React.js, 스프링 부트, AWS로 배우는 웹 개발 101
김다정 지음ㅣ에이콘출판ㅣ2022ㅣ도서 정보