☑️ CREATE
☑️ 컴포넌트 트리
를 그려보기 (유연한 사고력의 증진)
단방향 데이터 흐름
: 위에서 아래로만 데이터를 보낼 수 있음부모인 App 컴포넌트가 배열 형식의 State 데이터를 갖고, data 상태의 값을 DiaryList에게 전달하면서 list를 렌더링하게 하고 이 data라는 상태를 변화시킬 수 있는 상태 변화함수인 setData를 DiaryEditor에게 prop으로 전달해주기만 하면 됨
트리 형태
구조를 띰단방향 데이터
구조setData
상태변화함수를 통해 props
으로 전달state 끌어올리기
: 이렇게 여러 개의 컴포넌트에 엮인 데이터를 공통 부모인 App 컴포넌트의 state로 설정하여 문제 해결하는 방법☑️ src/App.js
import { useRef, useState } from "react";
import "./App.css";
import DiaryEditor from "./DiaryEditor";
import DiaryList from "./DiaryList";
function App() {
// 전역적으로 상태관리
// 일기데이터, 빈 배열로 시작 (일기가 없는 상태로 출발)
const [data, setData] = useState([]);
// 데이터가 하나씩 추가될 때마다 id가 1,2,3.. 이렇게 추가되도록
// 변수처럼 사용할 고유 id가 생성되도록 useRef를 통해 추가
// 0번 index부터 시작
const dataId = useRef(0);
// 새로운 일기를 추가하는 함수
// 파라미터로 값들을 받아온다
const onCreate = (author, content, emotion) => {
const created_date = new Date().getTime(); // 현재시간 구하기. 시간 객체
const newItem = { // 새로운 아이템
author,
content,
emotion,
created_date,
id: dataId.current // 어떤 DOM도 선택하지 않고 현재 0이란 값을 갖고 있음
};
dataId.current += 1; // 새 아이템을 만들고 0번은 1번으로 증가
// 원래 data를 spread연산자로 쓰고(원래 배열에 있던 data를 여기에)
// 새로운 아이템을 추가하고 원래 데이터를 이어붙이는 형태
setData([newItem, ...data]);
};
return (
<div className="App">
<DiaryEditor onCreate={onCreate} /> {/* 새 일기 추가를 prop으로 내려준다 */}
<DiaryList diaryList={data} /> {/* data를 prop으로 내려준다 */}
</div>
);
}
export default App;
☑️ src/DiaryEditor.js
import { useState, useRef } from "react";
// DiaryEditor로 내린 onCreate 함수를 prop으로 전달
const DiaryEditor = ({onCreate}) => {
const [state, setState] = useState({
author: "", content: "", emotion: 1,
});
const authorInput = useRef();
const contentInput = useRef();
const handleChangeState = (e) => {
setState({
...state,
[e.target.name]: e.target.value,
});
};
const handleSubmit = () => {
if(state.author.length < 1) {
// alert("작성자는 최소 1글자 이상 입력해주세요.");
// focus
authorInput.current.focus();
return;
}
if(state.content.length < 5){
// alert("일기 본문은 최소 5글자 이상 입력해주세요.");
// focus
contentInput.current.focus();
return;
}
// props로 받은 onCreate 함수를 호출하기
onCreate(state.author, state.content, state.emotion);
alert("저장 성공");
// 저장 후 작성폼이 초기화되도록 setState 설정
// 일기를 한번 더 쓰면 원래 상태로 초기화
setState({
author: "", content: "", emotion: 1
});
};
return (
<div className="DiaryEditor">
<h2>오늘의 일기</h2>
<div>
<input ref={authorInput} name="author" value={state.author} onChange={handleChangeState} />
<span className="notification">작성자명을 입력하세요 (최소 1글자 이상)</span>
</div>
<div>
<textarea ref={contentInput} name="content" value={state.content} onChange={handleChangeState} />
<span className="notification">일기 본문을 입력하세요 (최소 5글자 이상)</span>
</div>
<div>
<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>
<span className="notification">감정 점수를 선택하세요 (택 1)</span>
</div>
<div>
<button onClick={handleSubmit}>저장하기</button>
</div>
</div>
);
};
export default DiaryEditor;
App 컴포넌트 : DiaryEditor 컴포넌트와 DiaryList 컴포넌트로 함께 사용할 일기 데이터 하나를 가지고 있음
초기 상태
state로 일기 데이터는 빈 배열로 시작 (처음엔 작성된 일기가 없으므로)
일기상태변화 함수 setData를 가지고 있음
이 상태에서는 DiaryList한테 현재 이 App 컴포넌트가 가진 일기 배열 데이터의 상태를 넘겨주기만 하면, DiaryList도 알아서 다시 렌터하고 추가하면 추가, 삭제하면 삭제 (상태 바뀜)
상태 변화
DiaryEditor 컴포넌트가 일기를 저장해서 반영되면 App 컴포넌트 데이터의 상태가 변화가 일어남
(DiaryList 컴포넌트가 App 컴포넌트의 data state를 DiaryList로 사용하고 있기 때문)
onCreate 함수 : 새로운 일기 추가 (DiaryEditor 컴포넌트에 props으로 전달)
일기 저장이 일어날 때 onCreate 함수를 호출
(emotion data, 현재 시간 객체, id ref +1 증가 등등)
가장 최신 일기 작성 시 가장 위로 배열에 들어감
단방향 데이터 흐름 그리고 역방향 이벤트 흐름으로 state를 끌어올려서 화면에 렌더링
✔️ 중간에 강의 듣다 헥갈릴까봐 클로바노트
로 녹음하는데,
헥갈리는 부분은 글로 보면 이해하기 쉽다 🙂 (클로바짱짱!)