리액트로 프로젝트 할 때 실제로 펜을 잡고 컴포넌트 트리를 많이 그리게 될 것
- 리액트에서는 같은 레벨의 컴포넌트끼리 데이터를 주고받을 수 없음 => 단방향 데이터 흐름
DiaryEditor의 데이터를 DiaryList로 끌어오려면 공통 부모 요소로 끌어올려서 해결
부모 컴포넌트가 일기 데이터를 배열 형식의 State로 가지고 있고
DiaryList에 data를 전달해 렌더링하게 하고
DiaryEditor에 상태변화함수 setData를 prop으로 전달해주면 됨
추가된 item2까지 포함한 Data가<DiaryList/>
에 prop으로 내려가서 리렌더링됨
Data 추가하는 로직 "State 끌어올리기"
리액트로 만든 컴포넌트들은 이렇게 트리 형태의 구조
데이터는 아래나 위로만 움직이는 단방향 데이터 흐름
데이터 추가, 수정, 삭제 등 handling하는 event들은 props로 전달해서 아래에서 위로 올라가는 구조라고 생각할 수 있음
<DiaryEditor/>
에서 create 이벤트가 일어나면<App />
으로 전달되고
Data가 변화하게 되면<DayList/>
로 아래로 전달되는 흐름
(실습)
(App.js)
1. App.js에서 전역적으로 data 관리할 거니까 useState로 만들어주고(일기 데이터이므로 초기값 빈 배열[])
2. DiaryList.js에서 data를 사용할 것이므로 prop으로 내려주기
<DiaryList diaryList={data} />
3. data에 새로운 일기 추가하는 함수 만들기(onCreate)
4. onCreate 함수를<DiaryEditor onCreate={onCreate}/>
로 내려주기
=> diaryEditor에 작성한 author, content, emotion을 onCreate 함수가 받아서 setData를 이용해서 data에 업데이트시키는 로직
5. id는 useRef를 사용해 변수를 선언하면 된다.
useRef 사용 이유: 컴포넌트 내부에서 활용할 변수가 필요할 때 useState로 선언하게 되면 변수가 변경될 때마다 의미없는 리렌더를 유발
=> 따라서 렌더링과 관련없는 변수를 선언할 때는 useRef를 사용하는 것이 바람직하다
6.setData([newItem, ...data]);
새로운 일기 추가하면 제일 위로 올라오게, 원래 데이터도 보여줘야 하니까 spread 써서 펼쳐주기
(DiaryEdtior.js)
7. onCreate 함수 prop으로 받아주고 저장된 일기는 state에 담겨 있음
저장하는 부분 handleSubmit에서 호출해서 쓰기
onCreate(state.author, state.content, state.emotion);
// 일기 작성 후 저장하면 렌더링까지 완료