이어서...
- 리스트 렌더링(조회)
- 데이터 추가
- 데이터 삭제
- 데이터 수정
2. 데이터 추가
그럼 이제 가짜로 만든 데이터 말고 직접 작성한 데이터를 저장버튼을 누름으로써 리스트가 동적으로
추가되게 하는 기능을 만들어 보자
리액트에서 데이터는 단방향으로만 흐르기 때문에
리액트 컴포넌트 트리 구조에서 같은 레벨끼리는 데이터 주고받기를 못한다
그럼 어떤 식으로 데이터를 넘길수 있을까?
바로 state 끌어올리기 이다
state를 A와 B의 공통 부모 요소로 끌어올린다
이해가 쉽게 우리 프로젝트로 대입을 해보자
일기를 작성하는 DiaryEditor 컴포넌트가 있고, 일기를 추가하는 DiaryList 컴포넌트가 있다
data는 배열이고 item1이라는 하나의 일기 데이터를 가지고 있다 쳐보자
DiaryEditor에서 새로운 일기를 작성했다면 setData로 인하여 data 가 item2 가 추가된 값으로 리렌더 일어날 것이다
이렇게 하여 리액트는 event는 아래에서 위로 올라가고 data는 위에서 아래로 내려가는 성질이 있다는 걸 알 수 있다
그럼 첫 번째로 끌어올릴 state를 루트 컴포넌트에 생성해 보자
const [data,setData] = useState([]);
초기값이 빈배열인 이유는 일기 리스트를 배열에 담아서 관리하기 때문이다
다음 위의 그림처럼 prop을 넘겨주자
다음 가짜 데이터가 아닌 직접 작성한 내용을 리스트에 추가해야 하므로 추가하는 함수 하나를 만들어 주자
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,
}
dataId.current+=1;
setData(newItem,...data)
}
매개변수로 author, content, emotion을 가지고
작성 날짜를 생성해 준다
그 후 새로운 아이템으로 추가시켜줄 요소들을 newItem객체에 넣어준다
여기서 id는 아까의 가짜 데이터에서 직접 지정해주는 것이 아닌 동적으로 생성시켜줘야 하기 때문에
useRef를 사용한다 dataid를 0으로 초기화해주고 함수가 실행될 때마다 id를 +1 시켜준다
근데 여기서 궁금증이 발생했다 왜 useRef을 사용하는 거지? ↓
let dataId =0;
var dataId =0;
이런 식으로 그냥 변수로 주면 안 될까?
리액트에서 리렌더가 일어날 때를 다시 복기해 보자
1. 본인이 가진 state가 바뀔 때
2. 내가 부모로부터 받은 props가 바뀔 때
3. 자식인 내가 빈 깡통이라도 부모가 리렌더 된다면 자식인 나는 자동으로 리렌더가 된다
컴포넌트도 기본적으로 함수이다 리렌더가 일어난다는 것은 해당 함수가 재 실행되는 것이며
컴포넌트 함수 안에 let이나 var로 변수를 선언하고 초기화하시면 리렌더가 발생할 때 해당 변수가 다시 초기화되어 상태를 유지할 수 없다 또 컴포넌트 역할을 하는 함수가 재 실행되지 않으면 화면에 업데이트 즉 리렌더도 당연히 이루어지지 않는다.
즉 변수로 값을 주면 그 변수에 값은 증가할지라도 State는 변하지 않기 때문에 컴포넌트가 리렌더 되지 않고 따라서 화면에 안 보이게 된다
되도록 컴포넌트 내에서 변수를 사용하고 싶다면 useRef를 사용하는 게 좋다!!
값을 증가시키는 것만 생각했지 화면에 리렌더를 해야 한다는 걸 중요시 생각 안 했는데
아주 중요한 거였다.. 꼭꼭 기억하자!!!
그 후 setData 상태변화 함수에 우리는 새로 생성한 일기를 젤 위에 뜨게 할 것이므로
(newItem,... data) newItem 먼저 그다음에 스프레드 연산자로 지금까지의 data를 보내준다
<DiaryEditor onCreate={onCreate}/>
<DiaryList diaryList={data}/>
그 후 위의 그림처럼 DiaryEditor에는 상태를 변화하는 onCreate 함수를 prop으로 보내줘
create라는 이벤트를 위로 보내주는 것이다 DiaryList 에는 변화해서 올 데이터들을 다시 밑으로 보내준다
DiaryEditor에서 저장하기 버튼을 눌러 조건을 다 충족했으면 onCreate함수에 인자를 넣어서 App.js로 이벤트를 보내준다
후 컴포넌트 간에 흐름을 이해하는데 좀 힘들었다 점점 복잡해진다ㅠㅜ
아 그리고 onCreate함수를 호출한 후 setState의 값을 초기화시켜주는 거 잊지 말자
아니면 저장하고 이전에 썼던 일기 화면이 그대로 떠있다
새로 작성한 일기가 상단으로 잘 뜬다!
'개발새발🐶🐾🐥🐾 > React' 카테고리의 다른 글
[React] 리액트 useEffect? feat. Lifecycle (+예제코드) (1) | 2023.01.04 |
---|---|
[React Project: 간단한 일기장(5)] 배열사용해서 데이터 조작하기3- 데이터 삭제및 수정 (0) | 2023.01.03 |
[React Project: 간단한 일기장(3)] 배열사용해서 데이터 조작하기1- 리스트 렌더링 (0) | 2023.01.03 |
[React Project: 간단한 일기장(2)] DOM 조작하기 - useRef (0) | 2023.01.02 |
[React Project: 간단한 일기장(1)] React 사용자 입력 처리 (+ useState 활용) (0) | 2023.01.02 |