Search
🍔

React로 동적인 UI 만들기

Created
2023/05/11
Tags
JavaScript
React
CSS
HTML
Category
Project
Parent item
Sub-item
2 more properties
React로 맛집 공유 사이트 만들기

 구현할 기능

성수역, 강남역, 압구정역 총 세 개의 제목이 있고 현재 띄워지는 모달창에는 제목이 압구정역으로만 보이는데, 각 제목을 클릭하면 그에 맞는 모달창을 띄우고 싶다. 예를 들어, 성수역 제목을 클릭하면 성수역 맛집을 소개하는 모달창이 띄워지도록 말이다.
As-Is: 3개의 제목이 있으나 현재는 모달창에 1개의 제목으로만 뜸
To-be: 각 제목을 클릭하면 해당 제목을 가진 모달창을 띄우고 싶음

처음 작성한 코드

처음에는 제목당 1개씩 총 3개의 state를 만들어 주어야 하나, 아니면 타이틀 인덱스에 맞게 props를 내려주어야 하나 생각했다. 일단은 modalTitle이라는 state를 생성해주고, 삼항연산자 안에 넣어주었다.
import './App.css'; import logo from './logo.svg'; import { useState } from 'react'; function App() { let post = '🤙 나만 아는 맛집 제보하기'; let [title, setTitle] = useState(['성수역', '강남역', '압구정역']); let [thumb, setThumb] = useState([0,0,0]); let [modal, setModal] = useState(false); let [modalTitle] = useState(0); // 일단 state를 만들어줌
JavaScript
복사
{ title.map(function(a, i){ return ( <div className="list" key={i}> <h4 button onClick={() => { setModal(!modal) }}>{ title[i] })</h4> </div>) }) }
JavaScript
복사
// ... 생략 {modal === true ? <Modal title={title} setTitle={setTitle} modalTitle={modalTitle} // 삼항 연산자 안에 state를 넣어줌 /> : ''} <h4>{ post }</h4> </div> ); }
JavaScript
복사
function Modal(props) { return( <div className='modal'> <h4>{props.title[modalTitle]}</h4> // state를 작성해줌 </div> ) } export default App;
JavaScript
복사

 해결 과정

동적인 UI 구현하기 3steps

1. html css로 미리 디자인한다.

만들어져 있음. 패스.

2. 현재 UI의 상태를 state로 만들어 둔다.

성수, 강남, 압구정 세 가지 상태를 state에 저장해 두기. 완료했으니 패스.
// state 하나 더 추가 // 자료 형식은 number로 표현하겠음 (ex. 0이면 0번째 제목이 보이게끔) // 물론 string도 가능 let [modalTitle] = useState(0);
JavaScript
복사

3. state 종류에 따라 UI가 어떻게 보일지 작성한다.

ModalTitle의 인덱스가 i번째라면 i번째 제목이 나오게 만들어야 한다. 물론 각 제목을 클릭했을 때 해당 제목이 나오도록 3개의 조건문을 써도 되지만, 그럼 코드가 너무 복잡해지기 때문에 간략하게 표현해 보자.
그렇다면 제목 부분에 modalTitle이라는 state를 넣어주기만 하면 되는 것인가?
아니다.
여기서 주의할 점은 modalTitle이라는 state는 부모 컴포넌트인 function App에 선언되어 있으므로 not defined 에러가 뜬다.
function Modal(props) { return( <div className='modal'> <h4>{props.title[modalTitle]}</h4> .. // 'modalTitle' is not defined
JavaScript
복사
따라서 아래와 같이 자식 컴포넌트인 function Modal 안에 state를 props로 전송해 주어야 한다.
function Modal(props) { return( <div className='modal'> <h4>{ props.title[props.modalTitle] }</h4>
JavaScript
복사
다만 modalTitle이라는 state는 부모 컴포넌트인 function App 안에 있으므로 딱히 props로 내려 줄 필요가 없다. 아래와 같이 그대로 state를 적어준다.
{modal === true ? <Modal title={title} setTitle={setTitle} modalTitle={modalTitle} /> : ''}
JavaScript
복사
마지막으로, 우리의 본래 목적인 ‘ModalTitle의 인덱스가 i번째라면 i번째 제목이 나오게 만들어야 한다.'를 구현하기 위해 state 변경 함수도 추가한다.
let [modalTitle, setModalTitle] = useState(0);
JavaScript
복사
그리고 i 라는 변수를 활용해 모달 버튼을 클릭했을 때 해당 제목이 나오도록 만든다. map이라는 반복문 안에서 이 i는 반복문이 돌 때마다 0이 되고 1이 되고 2가 되게끔 만드는 변수다.
{ title.map(function(a, i){ return ( <div className="list" key={i}> <h4 button onClick={() => { setModal(!modal); setModalTitle(i) }}>{ title[i] })</h4> </div>) }) }
JavaScript
복사
론, 굳이 state를 props로 내려 줄 필요 없이 아래와 같이 function Modal에 state를 작성해 줄 수도 있겠지만, 이 modalTitle은 여러 군데에서 쓰인다면 최상위 컴포넌트인 function App에 작성해 주는 것이 좋다. state는 위에서 아래로는 전송해 줄 수 있지만, 아래에서 위로는 전송해 주지 못하기 때문이다.
function Modal(props) { let [modalTitle, setModalTitle] = useState(0); // state를 자식 컴포넌트에도 작성 return( <div className='modal'> <h4>{ props.title[props.modalTitle] }</h4>
JavaScript
복사

개선한 코드

import './App.css'; import logo from './logo.svg'; import { useState } from 'react'; function App() { let post = '🤙 나만 아는 맛집 제보하기'; let [title, setTitle] = useState(['성수역', '강남역', '압구정역']); let [thumb, setThumb] = useState([0,0,0]); let [modal, setModal] = useState(false); let [modalTitle, setModalTitle] = useState(0);
JavaScript
복사
{ title.map(function(a, i){ return ( <div className="list" key={i}> <h4 button onClick={() => { setModal(!modal); setModalTitle(i) }}>{ title[i] })</h4> </div>) }) }
JavaScript
복사
// ... 생략 {modal === true ? <Modal title={title} setTitle={setTitle} modalTitle={modalTitle} /> : ''} <h4>{ post }</h4> </div> ); }
JavaScript
복사
function Modal(props) { return( <div className='modal'> <h4>{ props.title[props.modalTitle] }</h4> </div> ) } export default App;
JavaScript
복사

기능 구현