과제 - React Custom Component
지금까지 우리는 컴포넌트 단위로 UI를 개발하는 이유와 컴포넌트 내부에 CSS를 작성하는 방법론인 CSS-in-JS에 대해서 배웠습니다. UI 컴포넌트를 제작하는 React Custom Component 과제를 진행하기에 앞서 다시 한번 필요성을 재고하며 시작해 봅시다.
UI 컴포넌트의 필요성
UI를 개발해 본 개발자라면 UI 개발은 다른 분야의 개발보다 복잡하고 까다롭다는 사실을 알 것입니다. UI 개발은 도대체 왜 까다로운 걸까요?
프로젝트의 상황에서 절대적으로 많은 수의 화면과 복잡한 화면이 문제입니다. 그래서 웹사이트의 모든 화면들을 분석해 보았습니다. 화면을 분석해 보니 몇 가지 패턴들을 발견할 수 있었습니다.
[그림] 프로젝트 내부에서 자주 사용되는 UI들의 모음
화면이 아무리 복잡하고 다양해도 기본적인 레이아웃 구성 내부에서 사용되는 UI들은 반복적으로 재사용되는 경우가 많습니다.
그렇다면 개발자들은 반복되는 UI들을 어떻게 재사용하고 있었을까요? 누군가 먼저 코드를 설계해 놓으면 그 코드를 비슷하게 쓰거나, 해당 UI가 어느 화면에 개발되어 있는지 알 수 없을 땐 새로 개발하기도 했습니다. 이런 크고 작은 불편함이 쌓여, 자연스럽게 UI 컴포넌트 개발에 대한 논의가 시작되었습니다.
개발팀들은 UI 컴포넌트를 도입함으로써 절대적인 코드량을 줄일 수 있었습니다. 더불어 화면이 절대적으로 많고 복잡도가 있는 프로젝트에서는 개발 기간 단축에 절대적으로 기여할 수 있는 장점이 있습니다.
디자인 시스템이란?
이러한 UI 컴포넌트들의 모음을 구조화하는 방법으로 디자인 시스템이라는 용어도 등장합니다.
디자인 시스템이란 서비스를 만드는 데 사용한 공통 컬러, 서체, 인터랙션, 각종 정책 및 규정에 관한 모든 컴포넌트를 정리해 놓은 것이며 불필요한 커뮤니케이션을 없애기 위해 체계적으로 정리한 시스템을 말합니다.
디자인 시스템의 인기는 폭발적으로 증가하고 있습니다. Airbnb와 같은 거대 기술 기업부터 신생 스타트업까지, 회사들은 시간과 비용을 절약하기 위해 UI 패턴을 재사용하는 방식을 도입하고 있습니다.
재사용이 가능한 사용자 인터페이스는 새로운 개념이 아닙니다. 스타일 가이드, UI 키트 및 공유 가능한 위젯은 수십 년 동안 존재해 왔습니다. 오늘날 디자이너와 개발자들은 UI 컴포넌트 구조화를 위해 노력하고 있습니다. UI 컴포넌트는 사용자 인터페이스를 이루는 조각들의 시각적이고 기능적인 속성을 캡슐화합니다. 마치 레고(LEGO) 블록처럼 말이죠!
최근에 등장한 유저 인터페이스(UI)들은 다양한 사용자 경험을 제공하기 위해 수백 개의 모듈식 UI 컴포넌트가 재배열된 구조로 이루어져 있습니다.
디자인 시스템은 재사용이 가능한 UI 컴포넌트들로 이루어져, 복잡하고 견고하며 사용자가 접근하기에 용이한 사용자 인터페이스를 구축할 수 있습니다. 디자이너와 개발자 모두 UI 컴포넌트를 다루기 때문에, 디자인 시스템은 두 분야를 연결하는 다리이기도 합니다. 또한 조직의 공용 컴포넌트에 대한 "진실의 근원(source of truth)"이기도 합니다.
Uber, Airbnb, IBM, GitHub을 비롯한 수백 개가 넘는 기업의 디자인 시스템에서 스토리북이 사용되고 있습니다. 아래 목록은 그중 가장 우수한 팀에서 사용되고 있는 Tool들입니다.
빌드 컴포넌트
- 📚 스토리북(Storybook): UI 컴포넌트 개발과 자동으로 문서를 생성할 때 사용합니다.
- ⚛️ 리액트(React): 선언 중심 컴포넌트 UI(create-react-app)를 사용합니다.
- 💅 스타일 컴포넌트(Styled-components): 컴포넌트 단위의 스타일링에 사용합니다.
- ✨ 프리티어(Prettier): 자동화된 코드 포맷팅에 사용합니다.
그래서 우리는 이번 과제에서 React, Styled-Component, Storybook을 활용해 UI 컴포넌트 개발을 경험해 볼 것입니다.
학습 목표
- Styled Components를 활용해 다양한 기능의 커스텀 컴포넌트를 구현할 수 있다.
- Storybook을 사용해 컴포넌트들을 관리할 수 있다.
과제 - React Custom Component
Getting Started
이번 과제에서는 Modal, Toggle, Tab, Autocomplete, ClickToEdit, Tag UI 컴포넌트들을 만들어보는데 목적을 둡니다. 현재는 App.js에서 모든 컴포넌트들을 불러와주고 있지만 App.js에서 불러오지 않고 있는 UI 컴포넌트를 만들어야 한다면 어떻게 눈으로 확인하며 개발을 진행할 수 있을까요? UI 컴포넌트들을 개발하며 동시에 Storybook에서 각각의 UI들이 어떻게 작동하는지 확인할 수 있습니다.
Repository
아래 링크에서 터미널을 이용하여 git clone 명령어로 Git Repository를 클론하고, npm install을 완료한 후 과제를 진행합니다. 이번 과제는 Bare minimum Requirement와 Advanced Challenge로 나누어져 있습니다. Bare minimum Requirement 테스트 케이스만 모두 통과하시면 됩니다.
npm script 소개
UI 컴포넌트 개발을 위해 필요한 tool 들인 Styled Components와 Storybook은 이미 설치가 되어 있습니다. package.json을 확인해 보세요!
- npm run start : 실제 React Web App을 개발 모드로 브라우저에서 실행시켜 볼 수 있습니다.
- npm run test : 기술 요구사항에 대한 유닛 테스트를 실행하고, 결과를 확인해 볼 수 있습니다. Bare Minimum Requirement는 모두 통과해야 합니다.
- npm run storybook : 각각의 UI 컴포넌트들을 애플리케이션 외부의 독립된 환경에서 개발할 수 있도록 도와줍니다. 스크립트 실행 후 http://localhost:6006에서 Storybook을 확인할 수 있습니다.
- Storybook의 코드는 이미 작성되어 있습니다. 여러분이 구현한 컴포넌트가 Storybook에서도 잘 표시되는 것을 확인해보세요.
File Structure
/
├── /React Custom Component
│ ├── README.md
│ ├── /public # create-react-app이 만들어낸 폴더로 yarn/npm start로 실행 시에 쓰입니다
│ └── /src
│ ├── /components # 단일 UI React 컴포넌트가 들어가는 폴더
│ ├─── /__test__ # 테스트 케이스가 들어가는 폴더
│ ├─── /AdvancedChallenges # Advanced Challenges 를 위한 폴더
│ ├─── /BareMinimumRequirements # Bare Minimum Requirements 를 위한 폴더
│ ├── /stories # Storybook이 작동하는 데 필요한 파일들이 들어가는 폴더
│ ├── app.css
│ ├── App.js # React Custom Component App이 작성되어 있습니다.
│ ├── index.js
├ package.json
└ .gitignore
Bare minimum Requirement
지금까지 배운 React, Styled Components를 활용하여 React-custom-component를 완성합니다.
- Modal, Toggle, Tab, Tag 컴포넌트를 구현합니다.
- npm run test 스크립트로 기본적인 기능을 테스트하는 테스트 케이스를 통과합니다.
- /src/tests/index.test.js 에서 구현할 컴포넌트의 테스트 주석을 하나씩 해제하면서 진행합니다.
- npm run storybook 스크립트로 컴포넌트들을 눈으로 확인하며 코드를 작성해, 하단 GIF 파일과 같은 모양을 구현합니다.
Modal Component 완성 예시
Modal UI 컴포넌트는 기존의 브라우저 페이지 위에 새로운 윈도우 창이 아닌, 레이어를 까는 것을 말합니다. (팝업창과는 차이가 있습니다. 어떤 차이가 있는지 직접 구글링을 통해 찾아보세요!) 현재 제공되고 있는 Modal.js는 Modal 버튼만 있고 아무 기능이 작동하지 않는 코드입니다. 아래 가이드라인을 따라 Modal 컴포넌트를 구현해 위의 GIF 파일과 같이 Modal 버튼을 클릭하면 Modal 창이 켜지고 꺼질 수 있게 구현하세요.
시작하기
Modal 컴포넌트 구현에 필요한 정보가 자세히 적혀있습니다. 확인 후 과제를 진행하세요.
- Modal 컴포넌트 테스트는 주석 처리가 되어있지 않습니다. 바로 진행해 주세요.
- Modal 컴포넌트는 아래와 같은 state가 존재합니다. 필요에 따라서 state를 더 만들 수도 있습니다.
- isOpen state는 모달 창의 열고 닫힘 여부를 확인할 수 있습니다.
- ModalBtn 컴포넌트는 모달 창 제어를 위해 핸들러 함수 openModalHandler를 작성합니다.
- openModalHandler 함수는
- ModalBtn 클릭 시 발생되는 change 이벤트 핸들러입니다.
- 클릭할 때마다 상태가 Boolean 값으로 변경됩니다.
- openModalHandler 함수는
- ModalView 컴포넌트를 작성하고 isOpen 상태가 true 일 경우에만 렌더링 합니다.
- ModalBackdrop 컴포넌트를 작성하고 isOpen 상태가 true 일 경우에만 렌더링 합니다.
요구사항
- Styled Components 라이브러리를 활용해 ModalContainer ModalBackdrop ModalBtn ModalView 컴포넌트의 CSS를 자유롭게 구현합니다.
- ModalContainer : Modal을 구현하는데 필요한 컴포넌트를 감싸주는 컨테이너 컴포넌트 역할을 합니다.
- ModalBackdrop : Modal이 떴을 때의 배경을 깔아주는 역할을 합니다.
- ModalBtn : Modal 창을 켜고 끌 수 있는 버튼입니다.
- ModalView : Modal 창 컴포넌트입니다.
- 구현한 Styled Components들을 Modal 컴포넌트 내부에서 활용합니다.
Modal 버튼 기능 테스트
- ModalBtn을 클릭하면 Modal이 열린 상태(isOpen)를 boolean 타입으로 변경하는 메서드가 실행되어야 합니다.
- 조건부 렌더링을 활용해서 Modal이 열린 상태(isOpen이 true인 상태)일 때만 모달창과 배경이 뜰 수 있게 구현해야 합니다.
- 조건부 렌더링을 활용해서 Modal이 열린 상태(isOpen이 true인 상태)일 때는 ModalBtn의 내부 텍스트가 'Opened!'로 Modal이 닫힌 상태(isOpen이 false인 상태)일 때는 ModalBtn의 내부 텍스트가 'Open Modal'이 되도록 구현해야 합니다.
Toggle Component 완성 예시
Toggle UI 컴포넌트는 두 가지 상태만을 가지고 있는 스위치입니다. 예를 들어, 한번 누르면 불이 들어오고 한번 누르면 불이 나가는 스위치를 Toggle Switch라고 할 수 있습니다. Toggle.js는 CSS는 거의 완성되어 있지만 기능은 작동하지 않습니다. 아래 가이드라인을 따라 Toggle 컴포넌트를 구현해 위의 GIF 파일과 같이 정상적으로 작동하도록 만들어 봅시다.
시작하기
Toggle 컴포넌트 구현에 필요한 정보가 자세히 적혀있습니다. 확인 후 과제를 진행하세요.
- 우선 Toggle 컴포넌트 테스트의 주석을 해제하고 시작합니다.
- Toggle 컴포넌트는 아래와 같은 state가 존재합니다. 필요에 따라서 state를 더 만들 수도 있습니다.
- isOn state는 토글 버튼의 on/off 여부를 확인할 수 있습니다.
- ToggleContainer 컴포넌트는 토글 버튼 제어를 위해 핸들러 함수 toggleHandler를 작성합니다.
- toggleHandler 함수는
- ToggleContainer 클릭 시 발생되는 change 이벤트 핸들러입니다.
- 클릭할 때마다 상태가 Boolean 값으로 변경됩니다.
- toggleHandler 함수는
요구사항
- Styled Components 라이브러리를 활용해 ToggleContainer Desc 컴포넌트의 CSS를 자유롭게 구현합니다.
- ToggleContainer : Toggle을 구현하는데 필요한 컴포넌트를 감싸주는 컨테이너 컴포넌트 역할을 합니다.
- Desc : Toggle Switch의 상태를 설명하는 텍스트를 담는 컴포넌트입니다.
- ToggleContainer 내부에 .toggle-container .toggle-circle 클래스를 가진 div 요소를 각각 생성합니다.
- 생성한 요소에 조건부 스타일링을 활용해 Toggle Switch가 ON인 상태일 경우에만 toggle--checked 클래스를 두 요소 모두에 추가합니다.
- 기본 CSS에서는 템플릿 리터럴과 삼항 연산자를 활용해 조건부 스타일링을 적용할 수 있습니다.
- <div className={`toggle-container ${isOn ? "toggle--checked" : ""}`} />
- 조건부 렌더링을 활용해 Toggle Switch가 ON인 상태일 경우에 Desc 컴포넌트 내부의 텍스트를 'Toggle Switch ON'으로 Toggle Switch가 OFF인 상태일 경우에는 'Toggle Switch OFF'로 변경합니다.
- 토글스위치가 부드럽게 옮겨지는 애니메이션 효과를 주기 위해서는 CSS의 transition 속성을 활용할 수 있습니다. 토글을 기능을 다 구현했다면 시도해 보세요!
Tab Component 완성 예시
Tab UI 컴포넌트는 동일한 메뉴 라인에서 뷰를 전환할 때 사용합니다. Tag.js는 CSS는 거의 완성되어 있지만 기능은 작동하지 않습니다. 아래 가이드라인을 따라 요구사항을 완성하여 Tab 컴포넌트가 정상적으로 작동하도록 만들어 봅시다. 또한 학습한 Styled Components 라이브러리를 활용하여 여러분만의 멋진 Tab 컴포넌트를 만들어 보세요.
시작하기
Tab 컴포넌트 구현에 필요한 정보가 자세히 적혀있습니다. 확인 후 과제를 진행하세요.
- 우선 Tab 컴포넌트 테스트의 주석을 해제하고 시작합니다.
- Tab 컴포넌트는 아래와 같은 state가 존재합니다. 필요에 따라서 state를 더 만들 수도 있습니다.
- currentTab state는 현재 tab의 index를 확인할 수 있습니다.
- TabMenu 컴포넌트는 토글 버튼 제어를 위해 핸들러 함수 selectMenuHandler를 가집니다.
- selectMenuHandler 함수는
- TabMenu 클릭 시 발생되는 change 이벤트 핸들러입니다.
- 클릭할 때마다 상태가 index 값으로 변경됩니다.
- selectMenuHandler 함수는
- li 요소를 이용해 메뉴를 생성하고, 각 메뉴를 눌렀을 때 뷰가 전환되도록 handler(selectMenuHandler) 함수를 작성합니다.
- 조건부 스타일링과 currentTab 상태를 이용하여 클릭한 Tab 메뉴만 className(submenu focused)과 CSS 가 변경되도록 구현합니다. 조건부 스타일링은 앞서 토글에서 구현한 것과 같이 템플릿 리터럴과 삼항 연산자를 활용할 수 있습니다.
요구사항
Component
- Styled Components 라이브러리를 활용해 TabMenu Desc 컴포넌트의 CSS를 자유롭게 구현합니다.
- TabMenu : Tab을 구현하는데 필요한 컴포넌트를 감싸주는 컨테이너 컴포넌트 역할을 합니다.
- Desc : Toggle Switch의 상태를 설명하는 텍스트를 담는 컴포넌트입니다.
TabMenu
- TabMenu 내부에 .submenu 클래스명을 가진 li 요소들을 map을 이용한 반복을 통해 생성합니다.
- TabMenu 내부에 .submenu 클래스명을 가진 li 요소의 textContent는 각 요소의 name입니다.
currentTab
- 조건부 렌더링을 활용해서 Tab 메뉴가 선택된 상태일 때, 선택된 Tab 메뉴 li 요소의 클래스명만 submenu focused 가 되어야 하고, 선택되지 않은 나머지는 submenu 가 되도록 구현해야 합니다.
- TabMenu를 클릭하면 현재 선택된 탭의 인덱스 값을 전달받아 currentTab 상태를 변경하는 selectMenuHandler 메서드가 실행되어야 합니다.
- TabMenu를 클릭하면 현재 선택된 탭 메뉴만 .focused CSS가 적용되어야 합니다.
- TabMenu를 클릭하면 Desc 컴포넌트의 content의 내용이 해당 탭의 content로 바뀌어야 합니다.
Tag Component 완성 예시
Tag UI 컴포넌트는 레이블 지정을 통해 구성이나 분류에 도움이 되는 키워드 집합을 만들 때 자주 사용됩니다. Tag.js 는 CSS는 거의 완성되어 있지만 기능은 작동하지 않습니다. 아래 가이드라인을 따라 요구사항을 충족하여 Tag 컴포넌트가 정상적으로 작동하도록 만들어 봅시다. 또한 학습한 Styled Components 라이브러리를 활용하여 여러분만의 멋진 Tag 컴포넌트를 만들어 보세요.
시작하기
Tag 컴포넌트 구현에 필요한 정보가 자세히 적혀있습니다. 확인 후 과제를 진행하세요.
- 우선 Tag 컴포넌트 테스트의 주석을 해제하고 시작합니다.
- Tag 컴포넌트는 아래와 같은 state가 존재합니다. 필요에 따라서 state를 더 만들 수도 있습니다.
- tags state는 배열의 형태입니다.
- 초깃값으로 initialTags를 가지고 있습니다.
- TagsInput 컴포넌트는 핸들러 함수 addTags를 가집니다.
- addTags 함수는
- input 창에 Enter 키를 누를 때 발생되는 change 이벤트 핸들러입니다.
- Enter를 입력할 때마다 입력한 값이 state에 추가됩니다.
- addTags 함수는
- span.tag-close-icon 에는 아직 실제 작동하는 삭제 아이콘(x)이 없습니다. 삭제 아이콘을 만들고, 이 버튼이 동작하도록 handler (removeTags ) 함수를 작성합니다.
- hint : 'HTML Entities'라는 키워드로 구글링 해서 참고해 보세요.
요구사항
input 기능 테스트
- input 창에 텍스트를 입력 후 Enter 키를 누르면 태그가 추가되어야 합니다. 마우스 클릭이 아닌 Enter 키를 통해 태그가 추가되도록 하며, Enter 키가 눌리면 태그를 추가하는 addTags 메서드가 실행되어야 합니다.
- addTags 메서드는 기본적으로 태그를 추가하는 기능 이외에 아래 세 가지 기능도 수행할 수 있어야 합니다.
- 이미 입력되어 있는 태그인지 검사하여 이미 입력되어 있다면 추가하지 말아야 합니다.
- 아무것도 입력하지 않은 상태에서는 Enter 키를 눌러도 addTags 메서드가 실행되지 않아야 합니다.
- 태그가 추가되고 나면 input 창이 비워져야 합니다.
삭제 기능 테스트
- 기본적으로 tags 배열 안의 모든 태그들이 화면에 보여야 합니다.
- 태그 이름 옆에 삭제 아이콘(x)이 표시되도록 하고, 아이콘을 클릭하면 해당 태그를 삭제하는 removeTags 메서드가 실행되어야 합니다.
- removeTags 메서드가 삭제 아이콘(x)이 눌린 태그를 삭제하도록 removeTags 메서드를 완성해야 합니다.
Advanced Challenge (Optional)
Bare minimum Requirement 구현에 성공했다면 Advanced Challenge에 도전하세요!
Autocomplete Component 완성 예시
Autocomplete UI 컴포넌트는 구글의 첫 화면과 같이 검색 폼처럼, 텍스트 input에 값을 입력하면, dropdown으로 input 값과 유사한 추천 검색 옵션을 보여주는 자동 완성 기능입니다. 사용자 경험을 향상할 수 있습니다.
Autocomplete.js에 컴포넌트가 어느 정도 작성되어 있습니다. 아래 가이드라인에 따라서 요구사항을 충족합니다.
시작하기
Autocomplete 컴포넌트 구현에 필요한 정보가 자세히 적혀있습니다. 확인 후 과제를 진행하세요.
- Autocomplete 컴포넌트는 아래 3가지 state가 존재합니다. 필요에 따라서 state를 더 만들 수도 있습니다.
- hasText state는 input 값의 유무를 확인할 수 있습니다.
- inputValue state는 input 값의 상태를 확인할 수 있습니다.
- options state는 input 값을 포함하는 autocomplete 추천 항목 리스트를 확인할 수 있습니다.
- input 요소를 만들고, input 값 제어를 위해 state와 핸들러 함수 handleInputChange를 작성합니다.
- handleInputChange 함수는
- input 값 변경 시 발생되는 change 이벤트 핸들러입니다.
- input 값과 상태를 연결시킬 수 있게 controlled component로 만들 수 있고
- autocomplete 추천 항목이 dropdown으로 시시각각 변화되어 보일 수 있도록 상태를 변경합니다.
- handleInputChange 함수는
- input 값에 맞는 옵션만 dropdown으로 보일 수 있도록 state와 핸들러 함수 handleDropDownClick를 작성합니다. deselectedOptions을 초깃값으로 이용해야 합니다.
- handleDropDownClick 함수는
- autocomplete 추천 항목을 클릭할 때 발생되는 click 이벤트 핸들러입니다.
- dropdown에 제시된 항목을 눌렀을 때, input값이 해당 항목의 값으로 변경되는 기능을 수행합니다.
- handleDropDownClick 함수는
- InputContainer의 자식으로 div.delete-button 가 있습니다. 이 버튼을 누르면 input 값을 초기화할 수 있어야 합니다.
- handleDeleteButtonClick 함수는
- input의 오른쪽에 있는 X버튼 클릭 시 발생되는 click 이벤트 핸들러입니다.
- handleDeleteButtonClick 함수를 완성하여 input값을 한 번에 삭제하는 기능을 구현합니다.
- handleDeleteButtonClick 함수는
요구사항
아래의 기본 기술 요구 사항에 맞게 UI Component를 제작합니다.
input 기능 테스트
- input 요소에 onChange 이벤트 핸들러가 불려 와야 합니다.
- input 값을 삭제할 수 있는 버튼(div.delete-button)이 있어야 합니다.
- 삭제 버튼 클릭 시 input value가 삭제되어야 합니다.
drop down 기능 테스트
- input 값이 포함된 자동 완성 추천 drop down 리스트가 보여야 합니다.
- drop down 항목을 마우스로 클릭 시, input 값 변경에 따라 drop down 목록이 변경되어야 합니다.
- drop down 항목을 마우스로 클릭 시, input 값이 변경되어야 합니다.
- drop down 항목을 마우스로 클릭 시, input 값이 이미 있어도 input 값이 drop down 항목의 값으로 변경되어야 합니다.
도전하기
- 키보드 방향 키로 drop down 목록을 조정할 수 있도록 구현합니다.
- 키보드 엔터키를 누르면 선택한 추천 검색어가 input 값이 되도록 구현합니다.
ClickToEdit Component 완성 예시
ClickToEdit 컴포넌트는 input 창을 클릭하면 수정이 가능하고, input 창이 아닌 다른 곳을 클릭하면 수정한 내용이 반영되는 기능을 가진 컴포넌트입니다.
시작하기
ClickToEdit 컴포넌트 구현에 필요한 정보가 자세히 적혀있습니다. 확인 후 과제를 진행하세요.
- 먼저 MyInput 컴포넌트를 구현하세요. MyInput 컴포넌트를 ClickToEdit 컴포넌트 내부에서 활용할 수 있습니다.
- MyInput 컴포넌트는 아래와 같은 state가 존재합니다. 필요에 따라서 state를 더 만들 수도 있습니다.
- isEditMode state는 boolean 값을 상태로 가집니다.
- newValue state는 보이게 될 값을 상태로 가지며, isEditMode 가 true 일 때 업데이트됩니다.
- ClickToEdit 컴포넌트는 아래와 같은 state가 존재합니다. 필요에 따라서 state를 더 만들 수도 있습니다.
- name , age를 state로 가지며, 앞서 작성한 MyInput 컴포넌트를 활용해 state를 업데이트할 수 있습니다.
- ClickToEdit 컴포넌트가 자식으로 가지는 MyInput 컴포넌트에 handleValueChange 메서드를 props로 받아 value를 업데이트하세요.
요구사항
MyInput 컴포넌트
- 조건부 렌더링을 활용하여 Edit가 가능한 상태일 경우에는 InputEdit 컴포넌트를 불러와야 합니다.
- input 요소에 onChange 이벤트 핸들러가 불러져 와야 합니다. onChange가 실행되면 저장된 value를 변경시켜 줍니다.
- input 요소에 onBlur 이벤트 핸들러가 불러져 와야 합니다. onBlur 이벤트 핸들러가 무슨 역할을 하는지 구글링을 통해서 찾아보세요!
- input 요소가 포커스를 잃었을 때, Edit가 불가능한 상태로 변경되어야 합니다.
- Edit가 불가능한 상태일 경우에는 저장된 value를 보여줄 수 있는 요소를 불러와야 합니다.
- 이 요소를 클릭하면 Edit 가 가능한 상태로 변경되어야 합니다.
input 창 클릭 기능 테스트
- 입력 가능 상태로 변경할 수 있는 onClick 이벤트 핸들러가 span 요소에 있어야 합니다.
- 포커스가 제외되는 이벤트 onBlur의 핸들러가 input 요소에 있어야 합니다.
- 텍스트 영역을 클릭하면 입력 가능 상태로 변경되어야 합니다.
- 입력 가능 상태일 때 변화가 감지되면 새로운 값을 설정하는 메서드가 실행되어야 합니다.
- 입력 가능 상태일 때 input이 아닌 다른 곳을 클릭하면 입력 불가 상태가 되어야 합니다.
- 입력 가능 상태일 때 input이 아닌 다른 곳을 클릭하면 input의 값이 span에 담겨야 합니다.