일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 개발자
- 탄스택쿼리
- 부트캠프
- 타입스크립트
- JavaScript
- 프론트엔드
- 인터넷
- hooks
- CSS
- HTML
- components
- 리액트쿼리
- Tanstack
- Tanstack Query
- react
- 자바스크립트
- 프론트
- 리액트
- TS
- JS
- 코딩
- 조건문
- 공식문서
- 개발
- 제로베이스
- 개발공부
- TypeScript
- 콜백
- 프론트엔드 스쿨
- props
Archives
- Today
- Total
SUE 개발 블로그
React ) 컴포넌트와 데이터 구조 본문
리액트는 기본적으로 단방향으로만 데이터가 흐른다. ( 단방향 데이터 흐름 )
상위 컴포넌트에서 가지고 있는 데이터를 하위 컴포넌트로 props 객체를 통해 전달하는 것을 props drilling.
함수를 통해 하위 컴포넌트 데이터를 상위 컴포넌트로 전달받아 사용할 수 있는데 이것을 상태 끌어올리기 state lifting 라고 한다.
리액트에서 만든 컴포넌트들은 위처럼 데이터는 위에서 아래로만 흐르는 단방향 흐름이고
추가, 수정, 삭제 같은 이벤트들을 핸들링 하는 setState 같은 함수를 props로 전달해 아래에서 위로 올리는 구조라고 볼 수 있다.
여러개의 컴포넌트에 엮인 데이터들을 그들의 공통 부모인 컴포넌트에 state 로 설정하여 문제를 해결.
일기를 작성하는 프로그램을 예제로 확인해보자.
import React, { useState, useEffect, useRef } from "react";
import DiaryEditor from "./DiaryEditor";
import DiaryList from "./DiaryList";
import "./App.css";
function App() {
const [data, setData] = useState([]);
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]);
};
return (
<div className="App">
<DiaryEditor onCreate={onCreate} />
<DiaryList diaryList={data} />
</div>
);
}
export default App;
최상위 부모 컴포넌트인 <App/> 에서 가지고 있는 data 를 하위 컴포넌트에게 props 로 보내준다.
이때 <DiaryEditor/> 에는 이벤트를 핸들링하는 함수를 함께 가지고있다.
import { useState, useRef } from "react";
const DiaryEditor = ({ onCreate }) => {
const authorInput = useRef();
const contentInput = useRef();
const [state, setState] = useState({
author: "",
content: "",
emotion: 1,
});
const handleChangeState = (e) => {
setState({
...state,
[e.target.name]: e.target.value,
});
};
const hanleSubmit = () => {
if (state.author.length < 1) {
authorInput.current.focus();
return;
}
if (state.content.length < 5) {
contentInput.current.focus();
return;
}
onCreate(state.author, state.content, state.emotion);
setState({
author: "",
content: "",
emotion: 1,
});
};
return (
<div className="DiaryEditor">
<h2>오늘의 일기</h2>
<div>
<input
ref={authorInput}
name="author"
value={state.author}
onChange={handleChangeState}
/>
</div>
<div>
<textarea
ref={contentInput}
name="content"
value={state.content}
onChange={handleChangeState}
></textarea>
</div>
<div>
<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>
<div>
<button onClick={hanleSubmit}>일기 저장하기</button>
</div>
</div>
</div>
);
};
export default DiaryEditor;
저장하기를 누르면 onCreate( ) 함수가 위로 올라가 <App/> 컴포넌트에 있던 data state 를 변화시키게 되고
import DiaryItem from "./DiaryItem";
const DiaryList = ({ diaryList }) => {
console.log(diaryList);
return (
<div className="DiaryList">
<h2>일기 리스트</h2>
<h4>{diaryList.length}개의 일기가 있습니다.</h4>
<div>
{diaryList.map((it) => (
<DiaryItem key={it.id} {...it} />
))}
</div>
</div>
);
};
DiaryList.defaultProps = {
diaryList: [],
};
export default DiaryList;
부모인 <App/> 에서 data 가 변화했기 때문에 <DiaryItem/> 는
다시 리랜더 되며 페이지를 새로 그려주는 걸 확인할 수 있다.
'React' 카테고리의 다른 글
React ) useReducer 리듀서 (0) | 2024.02.01 |
---|---|
React ) Lifecycle - React Hooks - useEffect (1) | 2024.01.10 |
React ) State & Event 스테이트와 이벤트 (1) | 2024.01.10 |
React ) map 함수와 key props (0) | 2024.01.10 |
React ) State 와 Props (1) | 2024.01.08 |