인프런 이정한님의 한입크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 ] 강의 수강 후 강의의 내용을 정리하며 공부한 것을 쓴 게시글입니다.
React에서 사용자 입력 처리하기
- DiaryEditor 컴포넌트가 필요한 것
- 작성자
- 일기본문
- 감정 점수
- 작성자, 일기 본문, 감정 점수를 state로 저장하고 변경한다.
- 하나의 state로 객체 배열을 관리할 수 있다.
- 초기값은 빈 문자열과 1로 설정한다.
const [state, setState] = useState({
author: "",
content: "",
emotion: 1
});
- setState를 할 때에는 spread 연산자(...)를 이용해, 바꾸고자 하는 것을 제외하고는 원본을 유지한다.
- [e.target.name]: e.target.value
-> state배열 원소 중 e.target.name 의 값을 key로 가진 객체의 value값을 e.target.value로 바꾼다.
const handleChangeState = (e) => {
setState({
...state,
[e.target.name]: e.target.value
});
};
- onChange : value 변화를 감지
- onClick : Click Event 감지
- 작성자
<input
name="author"
value={state.author}
placeholder="author"
onChange={handleChangeState} />
- 일기 본문
<textarea
name="content"
value={state.content}
placeholder="content"
onChange={handleChangeState} />
- 감정 점수
<span>오늘의 감정점수 : </span>
<select
name="emotion"
value={state.emotion}
onChange={handleChangeState}>
<option value={1}>1</option>
<option value={2}>2</option>
<option value={3}>3</option>
<option value={4}>4</option>
<option value={5}>5</option>
</select>
- 저장 버튼
<button onClick={handleSubmit}>저장</button>
React에서 DOM 조작하기
# DiaryEditor.js
- useRef로 특정 DOM 선택하기
const authorInput = useRef();
const contentInput = useRef();
- input 태그와 textarea 태그 각각에 ref={authorInput}, ref={contentInput} 추가
- handleSubmit 함수 수정
- 작성자 이름이 1글자 미만이면 저장되지 않고, 작성자 이름 입력 칸으로 focus
- 일기 본문이 5글자 미만이면, 저장되지 않고, 일기 본문 입력 칸으로 focus
const handleSubmit = () => {
if (state.author.length < 1) {
authorInput.current.focus();
return;
}
if (state.content.length < 5) {
contentInput.current.focus();
return;
}
alert("저장 성공!");
}
React에서 배열 사용하기 (CRUD)
# App.js
- 일기 리스트를 저장할 배열 data - state로 사용
const [data, setData] = useState([]);
- 각각의 일기의 아이디 값을 저장할 dataId - ref로 사용
const dataId = useRef(0);
- 일기 생성 시 호출 할 함수 : onCreate
- 기존 저장 버튼을 눌렀을 때 실행되던 함수에 onCreate 추가해 data를 저장하게 함
const onCreate = (author, content, emotion) => {
const created_date = new Date().getTime();
const newItem = {
author,
content,
emotion,
created_date,
id: dataId.current,
};
dataId.current += 1;
setData([newItem, ...data]);
};
- 일기 삭제 시 호출할 함수 : onRemove
- 삭제 할 일기의 id를 targetId로 전달받아 해당 id의 객체를 제외한 나머지 객체들로 새 객체 생성 해 setData
const onRemove = (targetId) => {
const newDiaryList = data.filter((it) => it.id !== targetId);
setData(newDiaryList);
};
- 일기 수정 시 호출할 함수 : onEdit
- 수정 할 일기의 id를 targetId로 전달받고, map으로 배열을 돌면서 해당 id의 객체의 content를 전달받은 newContent 값으로 바꿈
const onEdit = (targetId, newContent) => {
setData(
data.map((it) =>
it.id === targetId ? { ...it, content: newContent } : it
)
);
};
- DiaryList 호출 시 onRemove 함수와 onEdit 함수를 전달하고, DiaryList에서 DiaryItem을 호출할 때 두 함수를 넘겨 받음
# DiaryList.js
- 전달받은 diaryList 를 map으로 돌며, 각각의 일기의 DiaryItem을 생성
const DiaryList = ({ onRemove, onEdit, diaryList }) => {
return (
<div className="DiaryList">
<h2>일기 리스트</h2>
<h4>{diaryList.length}개의 일기가 있습니다.</h4>
<div>
{diaryList.map((it) => (
<DiaryItem key={it.id} {...it} onRemove={onRemove} onEdit={onEdit} />
))}
</div>
</div>
);
};
# DiaryItem.js
- 수정작업 중일 때를 뜻하는 isEdit - state로 사용하고, 기본 값은 false
- toggleEdit 함수는 toggle 처럼 isEdit이 true값일때는 false로, false 값일 때는 true 값으로 바꿈
const [isEdit, setIsEdit] = useState(false);
const toggleIsEdit = () => setIsEdit(!isEdit);
- 수정 중인 일기의 내용의 값인 localContent - state로 사용
const [localContent, setLocalContent] = useState(content);
- 삭제 버튼 클릭하면 호출되는 함수 : handleRemove
- 사용자에게 삭제할 것인지 물어보고, 확인을 클릭하면 App.js에서 선언한 onRemove 함수 호출
const handleRemove = () => {
if (window.confirm(`${id + 1}번째 일기를 삭제하시겠습니까?`)) {
onRemove(id);
}
};
- 수정 버튼을 클릭하고, 수정 후 완료 벼튼을 클릭하면 호출되는 함수 : handleEdit
- 사용자가 수정한 내용의 글자 수가 5 미만이라면, 해당 입력 칸에 focus하여 다시 입력하도록 함
- 사용자에게 수정할 것인지 물어보고, 확인 버튼을 클릭하면, App.js에서 선언한 onEdit 함수 호출
- isEdit을 다시 false로 바꾸도록 toggleEdit 함수 호출
const handleEdit = () => {
if (localContent.length < 5) {
localContentInput.current.focus();
return;
}
if (window.confirm(`${id + 1}번째 일기를 수정하시겠습니까?`)) {
onEdit(id, localContent);
toggleIsEdit();
}
};
- 일기 수정 중에 (수정)취소 버튼 클릭하면 호출 되는 함수 : handleQuitEdit
- isEdit을 false로 바꾸고, 화면에 보이는 일기의 내용을 원래의 값으로 다시 보여지도록 함
const handleQuitEdit = () => {
setIsEdit(false);
setLocalContent(content);
};
- 수정 중임을 나타내는 isEdit의 값이 true일 때는 textarea로 수정할 수 있도록 하고, false일 때는, 해당 일기의 content값이 보여지도록 함
<div className="content">
{isEdit ? (
<>
<textarea
ref={localContentInput}
value={localContent}
onChange={(e) => setLocalContent(e.target.value)}
/>
</>
) : (
<>{content}</>
)}
</div>
- isEdit이 true이면 (수정)취소, (수정)완료 버튼이 보여지도록 하고, false이면 삭제, 수정 버튼이 보여지도록 함
{isEdit ? (
<>
<button onClick={handleQuitEdit}>취소</button>
<button onClick={handleEdit}>완료</button>
</>
) : (
<>
<button onClick={handleRemove}>삭제</button>
<button onClick={toggleIsEdit}>수정</button>
</>
)}
'FRONTEND > React' 카테고리의 다른 글
[ 인프런 - 한입 크기로 잘라 먹는 React] 3. React 실전 프로젝트 - 감정 일기장 만들기(2) (0) | 2023.01.09 |
---|---|
[ 인프런 - 한입 크기로 잘라 먹는 React] 3. React 실전 프로젝트 - 감정 일기장 만들기(1) (0) | 2023.01.08 |
[ 인프런 - 한입 크기로 잘라 먹는 React] 2. React 기본 - 간단한 일기장 프로젝트 (2) (0) | 2023.01.06 |
[ 인프런 - 한입 크기로 잘라 먹는 React ] 1. React 기초 (0) | 2022.12.30 |
[ 생활코딩 Web2 - React ] 컴포넌트, props, 이벤트, state, create, update (0) | 2022.12.11 |