DB 연결 없는 Version
const [memos, setMemos] = useState([
{
id: 0,
title: '제목1',
author: '익명1',
content: '메모1'
},
{
id: 1,
title: '제목2',
author: '익명2',
content: '메모2'
},
{
id: 2,
title: '제목3',
author: '익명3',
content: '메모3'
},
]);
⇒ 배열에 데이터 저장하여 사용
//App.js
const nextId = useRef(3);
const onInsert = useCallback(
(title, author, content) => {
const memo = {
id: nextId.current,
title,
author,
content
};
setMemos(memos.concat(memo));
nextId.current += 1;
},
[memos],
);
<Modal state={modalState} closeModal={closeModal} onInsert={onInsert} />
onInsert( )
→ Modal.js에 전달
//Modal.js
const onSubmit = useCallback(
e => {
onInsert(title, author, content);
e.preventDefault();
setTitle('');
setAuthor('');
setContent('');
closeModal();
},
[onInsert, title, author, content],
)
등록 버튼 클릭 시 - onSubmit()
1. 데이터 목록 보여주기
{memos.map(memo => (
<td className='cell' onClick={() => openReModal(memo.id)}>
<div className='inner'>
<h2>{memo.title}</h2>
<h5>{memo.author}</h5>
<h4>{memo.content}</h4>
</div>
</td>
))}
2. ReModal 창에 기존 정보 값 표시
//App.js
const [clickmemo, setClickmemo] = useState({
id: '',
title: '',
author: '',
content: '',
})
const openReModal = (id) => {
setClickmemo({
id: id,
title: memos[id].title,
author: memos[id].author,
content: memos[id].content,
});
setReModalState(true);
}
<ReModal state={reModalState} closeModal={closeReModal} onRemove={onRemove} onUpdate={onUpdate} />
openReModal 시, 클릭한 메모에 대한 정보를 clickMemo에 저장
→ ReModal.js에 clickmemo값을 data로 전달
//ReModal.js
const [title, setTitle] = useState(data.title);
const [author, setAuthor] = useState(data.author);
const [content, setContent] = useState(data.content);
useEffect(() => {
console.log(title, author, content);
setTitle(data.title);
setAuthor(data.author);
setContent(data.content);
}, [data]);
useState 이용하여 title, author, content에 초기값 지정
→ useEffect 이용해서 data 값이 변경되면 값을 변경해줌
🚨 ISSUE 🚨
useState로 초기값 설정을 주었으나, 의도한 대로 표시되지 않음
클래스형으로 표현할 때는 componentWillReceiveProps()를 사용했으나, 함수형은 이를 사용할 수 없음.
따라서, useEffect를 이용해서 해결하기
//App.js
const onUpdate = useCallback(
(id, change_memo) => {
closeReModal();
setMemos(memos.map((memos, index) =>
index === id ? { id, ...change_memo } : memos
))
}, [memos],
)
<ReModal state={reModalState} closeModal={closeReModal} data={clickmemo} onRemove={onRemove} onUpdate={onUpdate} />
onUpdate()
💡 spread 연산자(...)
⇒ state 관리 시, 불변성 유지한 채 일부 특정 값만 변경(update) 시, 사용
const objA = { a:1, b:2, c:3 };
const objB = { ...objA, b:4 }; //objA 복제 후, b속성만 덮어쓰기
→ ReModal.js로 전달
//ReModal.js
const handleUpdate = useCallback(e => {
onUpdate(data.id, {
title,
author,
content
})
e.preventDefault();
closeModal();
})
handleUpdate()
//App.js
const onRemove = useCallback(
id => {
closeReModal();
setMemos(memos.filter(memo => memo.id !== id));
},
[memos],
);
<ReModal state={reModalState} closeModal={closeReModal} data={clickmemo} onRemove={onRemove} onUpdate={onUpdate} />
onRemove()
→ ReModal.js에 전달
//ReModal.js
<button type="button" onClick={() => onRemove(data.id)}>
<p>삭제하기</p>
</button>
▶App.js
import React, { useState, useRef, useCallback } from 'react';
import './App.css';
import plus from './plus.png';
import Modal from './components/Modal';
import ReModal from './components/ReModal';
function App() {
const [memos, setMemos] = useState([
{
id: 0,
title: '제목1',
author: '익명1',
content: '메모1'
},
{
id: 1,
title: '제목2',
author: '익명2',
content: '메모2'
},
{
id: 2,
title: '제목3',
author: '익명3',
content: '메모3'
},
]);
const [modalState, setModalState] = useState(false);
const [reModalState, setReModalState] = useState(false);
const [clickmemo, setClickmemo] = useState({
id: '',
title: '',
author: '',
content: '',
})
// 모달창 열기
const openModal = () => {
setModalState(true);
}
// 모달창 닫기
const closeModal = () => {
setModalState(false);
}
// CREATE
const nextId = useRef(3);
const onInsert = useCallback(
(title, author, content) => {
const memo = {
id: nextId.current,
title,
author,
content
};
setMemos(memos.concat(memo));
nextId.current += 1;
},
[memos],
);
//re모달창 열기 (READ)
const openReModal = (id) => {
setClickmemo({
id: id,
title: memos[id].title,
author: memos[id].author,
content: memos[id].content,
});
setReModalState(true);
}
const closeReModal = () => {
setReModalState(false);
}
//DELETE
const onRemove = useCallback(
id => {
closeReModal();
setMemos(memos.filter(memo => memo.id !== id));
},
[memos],
);
//UPDATE
const onUpdate = useCallback(
(id, change_memo) => {
closeReModal();
setMemos(memos.map((memos, index) =>
index === id ? { id, ...change_memo } : memos
))
}, [memos],
)
return (
<div className="Container">
<div className='App'>
<h1>메모장</h1><br /><br />
<table>
<tbody>
<tr className='trList'>
{memos.map(memo => (
<td className='cell' onClick={() => openReModal(memo.id)}>
<div className='inner'>
<h2>{memo.title}</h2>
<h5>{memo.author}</h5>
<h4>{memo.content}</h4>
</div>
</td>
))}
<td className='cell'>
<div className="inner" onClick={openModal}>
<img src={plus} className='picture' alt='logo' />
</div>
</td>
</tr>
</tbody>
</table>
<main className='App'>
{/* 모달 연결 */}
<Modal state={modalState} closeModal={closeModal} onInsert={onInsert} />
<ReModal state={reModalState} closeModal={closeReModal} data={clickmemo} onRemove={onRemove} onUpdate={onUpdate} />
</main>
</div>
</div>
);
}
export default App;
▶Modal.js
import React, { useState, useCallback } from 'react';
import './Modal.scss';
function Modal({ state, closeModal, onInsert }) {
const [title, setTitle] = useState('');
const [author, setAuthor] = useState('');
const [content, setContent] = useState('');
const onChangeTitle = useCallback(e => {
setTitle(e.target.value);
});
const onChangeAuthor = useCallback(e => {
setAuthor(e.target.value);
});
const onChangeContent = useCallback(e => {
setContent(e.target.value);
});
const onSubmit = useCallback(
e => {
onInsert(title, author, content);
e.preventDefault();
setTitle('');
setAuthor('');
setContent('');
closeModal();
},
[onInsert, title, author, content],
)
return (state ?
<React.Fragment>
<div className="Modal-overlay" >
<div className="Modal">
<h1 className="title">메모를 기록하세요!</h1>
<form onSubmit={onSubmit}>
<div className="content">
<h4>
<input type="text" placeholder="아이디를 입력하세요"
name="author" value={author}
onChange={onChangeAuthor}></input>
</h4>
<br />
<h4>
<input type="text" placeholder="제목을 입력하세요"
name="title" value={title}
onChange={onChangeTitle}></input>
</h4>
<textarea name="content" value={content}
onChange={onChangeContent}>
</textarea>
</div>
<div className="button-wrap">
<button type="submit">
<p>메모 추가하기</p>
</button>
<button type="submit" onClick={e => closeModal(e)}>
<p>닫기</p>
</button>
</div>
</form>
</div>
</div>
</React.Fragment>
: null);
};
export default Modal;
▶ReModal.js
import React, { useState, useCallback, useEffect } from 'react';
import './Modal.scss';
function ReModal({ state, data, onRemove, onUpdate, closeModal }) {
const [title, setTitle] = useState(data.title);
const [author, setAuthor] = useState(data.author);
const [content, setContent] = useState(data.content);
const onChangeTitle = useCallback(e => {
setTitle(e.target.value);
});
const onChangeAuthor = useCallback(e => {
setAuthor(e.target.value);
});
const onChangeContent = useCallback(e => {
setContent(e.target.value);
});
useEffect(() => {
console.log(title, author, content);
setTitle(data.title);
setAuthor(data.author);
setContent(data.content);
}, [data]);
const handleUpdate = useCallback(e => {
onUpdate(data.id, {
title,
author,
content
})
e.preventDefault();
closeModal();
})
return (state ?
<React.Fragment>
<div className="Modal-overlay" >
<div className="Modal">
<h1 className="title">메모를 기록하세요!:D</h1>
<form onSubmit={handleUpdate}>
<div className="content">
<h4>
<input type="text" placeholder="아이디를 입력하세요"
name="author" value={author}
onChange={onChangeAuthor}></input>
</h4>
<br />
<h4>
<input type="text" placeholder="제목을 입력하세요"
name="title" value={title}
onChange={onChangeTitle}></input>
</h4>
<textarea name="content" value={content}
onChange={onChangeContent}>
</textarea>
</div>
<div className="button-wrap">
<button type="submit">
<p>수정하기</p>
</button>
<button type="button" onClick={() => onRemove(data.id)}>
<p>삭제하기</p>
</button>
</div>
</form>
</div>
</div>
</React.Fragment>
: null);
};
export default ReModal;
[리액트를 다루는 기술] 11장 컴포넌트 성능 최적화 (0) | 2021.12.27 |
---|---|
React와 Express를 사용해 메모장 만들기(Hooks 사용 ver.) (0) | 2021.12.01 |
[리액트를 다루는 기술] 9장 컴포넌트 스타일 (0) | 2021.11.15 |
[리액트를 다루는 기술]7장 컴포넌트의 라이프사이클 메서드 (0) | 2021.11.08 |
[리액트를 다루는 기술]8장 Hooks (0) | 2021.11.08 |