-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[4단계 미션] 박예은 미션 제출합니다 #28
Changes from all commits
fe6716b
e58cc30
57849c4
16b7b7f
efed817
c3c5fc7
6c6c45b
972cf6e
8e5e16b
8794dae
80dce59
e02a97a
29016c0
f41ced4
19d8f6e
b73b1f5
d364767
71bffb8
cc49523
c6721b7
7124439
c7e8c08
f25a0fd
9e06b51
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,73 @@ | ||
import "../styles/AddRestaurantModalStyle.css"; | ||
import { CATEGORY_DATA } from "../data/categoryData"; | ||
import { useState } from "react"; | ||
|
||
function AddRestaurantModal({ setIsAddModalOpen, handleAddRestaurant }) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
깔끔하고 직관적인 이름이네요 👁️ |
||
const [newRestaurant, setNewRestaurant] = useState({ | ||
id: Date.now(), | ||
name: "", | ||
description: "", | ||
category: "", | ||
}); | ||
|
||
const handleAddBtnClick = () => { | ||
handleAddRestaurant(newRestaurant); | ||
setIsAddModalOpen(false); | ||
}; | ||
|
||
function AddRestaurantModal() { | ||
return ( | ||
<div className="modal modal--open"> | ||
<div className="modal-backdrop"></div> | ||
<div className="modal-backdrop" onClick={() => setIsAddModalOpen(false)}></div> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍👍 |
||
<div className="modal-container"> | ||
<h2 className="modal-title text-title">새로운 음식점</h2> | ||
<form> | ||
<div className="form-item form-item--required"> | ||
<label htmlFor="category text-caption">카테고리</label> | ||
<select name="category" id="category" required> | ||
<select | ||
name="category" | ||
id="category" | ||
required | ||
onChange={(event) => | ||
setNewRestaurant({ ...newRestaurant, category: event.target.value }) | ||
} | ||
> | ||
<option value="">선택해 주세요</option> | ||
{CATEGORY_DATA.slice(1).map((category) => ( | ||
<option key={category}>{category}</option> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 인터뷰 🎤
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저번주 스터디에서 배운 내용을 적용했어요!! key prop이 바뀌면 리렌더링 됩니다. 따라서 아래 두 가지 상황을 피해야 한다고 배웠어요.
이러한 이유로 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. key를 사용할 때 피해야 하는 상황을 잘 말씀해주셨네요 🚀 말씀해주신 예시인 [즉석에서 생성한 값을 전달] 의 경우에는 매 리렌더링마다 보통 새로운 값이 랜덤으로 생성되는 방법을 사용하기 때문에 React에서 key 값을 이용해 각 항목들을 식별하는 의미가 없어집니다. 항목이 계속해서 같은 키 값을 가지고 있어야 리스트의 여러 항목이 변경되더라도 그 항목을 식별하고 이를 이용해 더 최적화된 연산을 수행할 수 있는데, 매번 키 값이 새롭게 생성되면 React 입장에서는 실제로는 항목이 이동한 것에 불과한데도 새로운 항목이 추가된 것으로 인식하고 불필요한 연산들을 수행하려 할 겁니다.
여기에 말씀하신 내용에 대해 좀 더 자세한 내용을 적어드릴게요. 리렌더링은 적절하게 key 값을 사용했을 때 작성하신 코드는 재조정(Reconcilation) 과정에서 활약할 수 있게 됩니다. 컴포넌트가 리렌더링되야 할 경우 React는 변경 사항을 비교하고 이를 기반으로 새로운 DOM 트리를 그려야 합니다. 이 때 key값을 기반으로 매번 트리를 새로 그리거나 새로운 DOM 요소를 비싼 비용으로 추가하지 않고 기존에 존재하는 DOM을 재사용할 수 있게 됩니다. |
||
))} | ||
</select> | ||
|
||
</div> | ||
|
||
<div className="form-item form-item--required"> | ||
<label htmlFor="name text-caption">이름</label> | ||
<input type="text" name="name" id="name" required /> | ||
<input | ||
type="text" | ||
name="name" | ||
id="name" | ||
required | ||
onChange={(event) => setNewRestaurant({ ...newRestaurant, name: event.target.value })} | ||
/> | ||
</div> | ||
|
||
<div className="form-item"> | ||
<label htmlFor="description text-caption">설명</label> | ||
<textarea name="description" id="description" cols="30" rows="5"></textarea> | ||
<textarea | ||
name="description" | ||
id="description" | ||
cols="30" | ||
rows="5" | ||
value={newRestaurant.description} | ||
onChange={(event) => | ||
setNewRestaurant({ ...newRestaurant, description: event.target.value }) | ||
} | ||
></textarea> | ||
<span className="help-text text-caption">메뉴 등 추가 정보를 입력해 주세요.</span> | ||
</div> | ||
|
||
<div className="button-container"> | ||
<button className="button button--primary text-caption">추가하기</button> | ||
<button className="button button--primary text-caption" onClick={handleAddBtnClick}> | ||
추가하기 | ||
</button> | ||
</div> | ||
</form> | ||
</div> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ function CategoryFilter({ category, onChangeCategory }) { | |
className="restaurant-filter" | ||
aria-label="음식점 카테고리 필터" | ||
value={category} | ||
onChange={() => onChangeCategory(event.target.value)} | ||
onChange={(event) => onChangeCategory(event.target.value)} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔨 ✅ 👍🏻 |
||
> | ||
{CATEGORY_DATA.map((category) => ( | ||
<option key={category}>{category}</option> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
인터뷰 🎤
제어 컴포넌트(controlled component)와 비제어 컴포넌트(uncontrolled component)란 무엇인가요? 각 방법에서 부각되는 특징은 무엇이라고 생각하시나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
제어 컴포넌트(controlled component)
입력값이 상태에 의해 제어되는 컴포넌트입니다. input, textarea 등 입력 필드의 값이 바뀔 때마다 업데이트됩니다.
비제어 컴포넌트(uncontrolled component)
입력값이 상태에 의해 제어되지 않고 입력 필드가 값을 관리하는 컴포넌트 입니다. useRef를 사용해 필요할 때 입력값을 가져옵니다.
각 방법에서 부각되는 특징은 상태가 연결됐는지(컴포넌트와 입력값의 동기화) 여부라고 생각합니다!