working_helen
[React 일기장 프로젝트] UI 구성하기 본문
강의명 : 한입 크기로 잘라 먹는 리액트(React.js) - 섹션 5. React 기본 - 간단한 일기장 프로젝트
일기장 입력 + 저장 기본 구조 구축하기
1. 일기장 입력 컴포넌트 : DiaryEditor.js
2. 일기장 목록 컴포넌트 : DiaryList.js
3. 일기장 목록 아이템 컴포넌트 : DiaryItem.js
4. 전체 애플리케이션 컴포넌트 : App.js
일기장 컴포넌트 구조
1. 일기장 입력 컴포넌트 : DiaryEditor.js
1) [state, setState] - State 변수 생성
- 사용자 입력을 받아 값이 변화할 변수들 State 객체 생성
- state = { author, content, emotion'}
2) handleChangeState - State 변수 변경 함수
- handleChangeState : event e에 대하여 State 객체 내 하나의 State 변수 값을 변경
3) Reference 객체 생성
- Reference 객체 = 특정 컴포넌트를 가르키는 변수
- Reference객체.current = 현재 가르키는 컴포넌트
const ReferenceVariable = useRef();
4) handleSubmit - 일기장을 저장 + 잘못된 입력 시 focus와 경고창
(MDN) HTMLElement.focus() 메서드는 지정된 요소에 초점을 맞출 수 있는 경우 해당 요소에 초점을 설정
- HTML요소.focus()
- focus를 줄 객체가 무엇인지 가르키기 위해 Refernce 객체와 함께 사용
// Reference 변수가 현재 가르키고 있는 요소를 focus 한다
ReferenceVariable.current.focus()
5) DiaryEditor 리턴 입력창
- reference 변수가 가르키는 요소에, name과 value로 하는 handelChangeState 함수 수행
- 사용자 입력이 입력창에 그대로 나타나도록 State 변화를 구현한 것
- <input> : 사용자 인터페이스 상자를 만드는 태그, 입력 결과를 State 변수로 받음
==> 사용자 입력 받기 : <input> 태그 + State 변수
- <textarea> : 사용자가 여러 줄을 자유형식으로 작성할 수 있는 텍스트 편집 컨트롤러
<select> : 옵션을 제공 + 선택 기능의 컨트롤러, <option value={}> 태그와 함께 사용
<button> : 클릭으로 사용자의 입력을 받는 컨트롤러
[ Diary Editor 코드 ]
import { useRef, useState } from "react";
const DiaryEditor = () => {
//State 변수 생성 : 실행에 따라 값이 변하는 변수들 처리
const [state, setState] = useState({
// State 초기값 지정, 객체 형태
author:"",
content:"",
emotion: 5,
});
//Reference 객체 생성
const authorInput = useRef();
const contentInput = useRef();
//event e에 대해 하나의 state만 변화
const handleChangeState = (e) => {
setState({
// 전체 State 객체를 Spread
// 필요한 key만 value 변경
...state,
[e.target.name]: e.target.value,
});
};
const handleSubmit = () => {
// 잘못된 입력에 focus 주기
if(state.author.length<1){
authorInput.current.focus();
return;
}
if(state.content.length<5){
alert("본문을 5글자 이상 적어주세요.");
contentInput.current.focus();
return;
}
alert("저장 성공");
}
// DiaryEditor의 리턴
return (
<div className="DiaryEditor">
<h2>오늘의 일기</h2>
<div>
<input
ref = {authorInput} //reference 대상 지정
name = "author" //변수명
value={state.author} //변수값
onChange={handleChangeState}
/>
</div>
<div>
<textarea
ref = {contentInput}
name = "content"
value={state.content}
onChange={handleChangeState}
/>
</div>
<div>
오늘의 감정 점수 :
<select
name="emotion"
value={state.emotion}
onChange={handleChangeState}>
{/* select 값 후보들 */}
<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>
</div>
<div>
<button onClick={handleSubmit}>일기 저장하기</button>
</div>
</div>
)
};
export default DiaryEditor;
2. 일기장 목록 컴포넌트 : DiaryList.js
1) diaryList props 전달
- 일기장 배열 변수 diaryList 1개가 전달
- props 객체 내 원소가 하나일때, 해당 원소에 바로 접근 가능
(props.diaryList로 받지 않고 바로 diaryList 변수명 사용)
2) DiaryItem으로 props 전달
- diaryList에 있는 각 원소를 DiaryItem의 props로 전달
- 배열.map((원소) => (함수)) : 배열의 각 원소마다 함수를 적용한 결과 새로운 배열 반환
- key={item.id} : "Each child in a list should have a unique "key" prop." 에러를 해결, list의 각 원소가 구분될 수 있도록 각 원소마다 고유하게 가지고 있는 key값을 props의 key로 지정
- 배열의 각 원소마다 DiaryItem의 html 태그가 리턴
[ DiaryList.js 코드 ]
import DiaryItem from './DiaryItem.js'
// App으로 부터 diaryList 배열을 props로 전달받음
const DiaryList = ({diaryList}) =>{
// DiaryList의 리턴
return (
<div className = 'DiaryList'>
<h2>일기 리스트</h2>
<h4>{diaryList.length}개의 일기가 있습니다.</h4>
<div>
// DiaryItem으로 props 전달
{diaryList.map((item)=>(
<DiaryItem key={item.id} {...item}/>
// html 태그 리턴
))}
</div>
</div>
);
};
// defualt Props 정의
DiaryList.defaultProps = {
diaryList: [],
}
export default DiaryList;
3. 일기장 목록 아이템 컴포넌트 : DiaryItem.js
1) DiaryList의 props 전달
- DiaryList로부터 일기장 배열의 각 원소마다 {author, content, created_date, emotion, id} props 전달
2) DiaryItem의 리턴
- 각 일기장마다 작성자, 날짜, 감정 점수, 내용 정보 세트를 리턴
- <span> : 줄바꿈 되지 않는 인라인 요소
- 일반 정보는 'info' class로, 내용은 'content' class로 구분
- Date객체.toLocaleDateString() : 사람들이 사용하는 형식으로 날짜 표현 반환
[ DiaryItem.js 코드 ]
// props = {author, content, created_date, emotion, id}
const DiaryItem = (props) => {
// DiaryItem 리턴
return (
<div className = 'DiaryItem'>
<div className="info">
<span>작성자 : {props.author}</span>
<span className="date"> | {new Date(props.created_date).toLocaleDateString()}</span>
<div>감정 점수: {props.emotion}</div>
</div>
<div className="content">
<div>{props.content}</div>
</div>
</div>
);
};
export default DiaryItem;
4. 전체 애플리케이션 컴포넌트 : App.js
- DiaryEditor와 DiaryList 컴포넌트를 import
- App.css 파일로 style 지정
- Date().getTime() : 현재 시간을 받아서 ms 단위로 반환
- 일기장 배열을 DiaryList에 props로 전달
- App의 리턴 : DiaryEditor와 DiaryList의 html 코드를 리턴
[ App.js 코드]
import './App.css';
import DiaryEditor from './DiaryEditor';
import DiaryList from './DiaryList';
// 예시를 위한 일기장 배열
const dummyList = [
{id:1,
author: "haewon",
content:"Hello",
emotion: 5,
created_date: new Date().getTime(),
},
{id:2,
author: "Mark",
content:"Hi",
emotion: 2,
created_date: new Date().getTime(),
}
];
function App() {
return (
// App.css 적용을 위해 className을 'App'으로 지정
<div className="App">
<DiaryEditor />
{/* html 태그 리턴 */}
<DiaryList diaryList={dummyList}/>
{/* html 태그 리턴 */}
</div>
);
}
export default App;
'외부 수업 > React 스터디' 카테고리의 다른 글
[React 일기장 프로젝트] useEffect로 Lifycycle 제어 (0) | 2024.01.16 |
---|---|
[React 일기장 프로젝트] 데이터 추가, 삭제, 수정 구현 (0) | 2024.01.16 |
[React 기초] State / Props (0) | 2024.01.15 |
[React 기초] Node.js와 React.js 기본개념 (0) | 2024.01.15 |
[JavaScript 기초] JavaScript 응용 (0) | 2024.01.14 |