[Udemy] React 기본 - 일기장 만들기(3) READ

productuidev·2022년 4월 24일
1

React Study

목록 보기
21/52
post-thumbnail

React 기본 (Project)

Udemy - 한입크기로 잘라 먹는 리액트


📌 일기장 만들기 (3) - READ

Array.map((it) => <Component key={it.id} {...it} />)
  • 우리가 작성한 일기를 배열에 저장해보자.
  • 대부분의 웹사이트에서는 배열에다가 item들을 저장해서 List 또는 Feed 형태로 렌더링하는 사례들을 찾아볼 수 있음

☑️ src/DiaryList.js : 일기 list를 렌더링할 컴포넌트를 따로 하나 만들기

const DiaryList = ({}) => {
  return (
    <div className="DiaryList">
      <h2>일기 리스트</h2>
    </div>
  );
};

☑️ src/App.js : DiaryList.js 임포트, DiaryEditor의 자식 요소로 DiaryList 배치

import './App.css';
import DiaryEditor from './DiaryEditor';
import DiaryList from './DiaryList';

function App() {
  return (
    <div className="App">
      <DiaryEditor />
      <DiaryList />
    </div>
  );
}

export default App;

☑️ 일기 저장하기를 누르면 이 밑에 일기 리스트를 추가되도록 하기 위해 예시용으로 임시 배열(dummylist)를 만들어서 DiaryList에 Props로 데이터를 전달, 데이터를 list로 렌더링하기

  • 배열의 구성요소는 객체
  • 이 배열은 DiaryList 컴포넌트가 list로 렌더링할 역할은 한다
  • 일기도 데이터이기 때문에 모든 데이터는 고유한 id를 갖는다
  • create_date : 이 일기가 언제 작성됐는지 표시하기 위함
  • new Date() : 생성자 (시간 객체), 그냥 생성하면 현재 시간을 기준으로 생성됨
  • getTime() : 숫자를 반환하는 함수 *milliseconds(ms)로 변환
const dummyList = [
  {
    id:1,
    author: "PERSON 1",
    content: "HI 1",
    emotion: 5,
    create_date: new Date().getTime()
  },
  {
    id:2,
    author: "PERSON 2",
    content: "HI 2",
    emotion: 3,
    create_date: new Date().getTime()
  },  
  {
    id:3,
    author: "PERSON 3",
    content: "HI 3",
    emotion: 1,
    create_date: new Date().getTime()
  }, 
]

☑️ src/App.js : dummyList배열을 DiaryList 컴포넌트에 props으로 전달

function App() {
  return (
    <div className="App">
      <DiaryEditor />
      <DiaryList diaryList={dummyList} />
    </div>
  );
}

☑️ src/DiaryList.js : diaryList에도 props으로 전달하고 콘솔로 확인
☑️ 배열을 리스트로 렌더링 : map() 내장함수 사용 - 원소 한번 씩 순회(각각의 요소들이 div로 리턴한 결과 3개가 있는 배열이 되어 결과값이 된다)

const DiaryList = ({diaryList}) => {
  return (
    <div className="DiaryList">
      <h2>일기 리스트</h2>
      <h4>{diaryList.length} 개의 일기가 있습니다.</h4>
      <div>
        {diaryList.map((it)=>(
        	<div>일기 아이템</div>
        ))}
      </div>
    </div>
  );
};
// 이렇게 나오는 것과 같다

<div>일기 아이템</div>
<div>일기 아이템</div>
<div>일기 아이템</div>

☑️ 데이터를 직접 사용하기 : jsx를 쓰는 법과 같음

  • it은 diaryList 배열에 하나하나의 요소가 it으로 바뀌어서 들어오는 것
  • dummylist의 하나의 객체가 it으로 들어온다
const DiaryList = ({diaryList}) => {
  return (
    <div className="DiaryList">
      <h2>일기 리스트</h2>
      <h4>{diaryList.length} 개의 일기가 있습니다.</h4>
      <div>
        {diaryList.map((it)=>(
        	<div>
               <div>작성자 : {it.author}</div>
               <div>일기 : {it.content}</div>
               <div>감정 : {it.emotion}</div>
               <div>작성 시간(ms) : {it.create_date}</div>
            </div>
        ))}
      </div>
    </div>
  );
};

☑️ 배열을 실수로 내려주지 않았다면?

<DiaryList diaryList={undefined} />
  • TypeError : Cannot read properties of undefined (reading 'length')
  • deafaultProps : undefined로 전달될 것 같은 props들에 기본값을 설정해준다
  • 기본값은 빈 배열로 설정
DiaryList.defaultProps = { diaryList: [] }

☑️ 고유 id를 활용해 key prop 전달하기

  • 각각의 자식 요소들은 반드시 고유한 key prop으로 받아야 함
  • DiaryList 컴포넌트에 가서 보면 자식 컴포넌트를 key prop으로 받아야 하는 것을 알 수 있음
  • dummylist 배열을 만들 때 item별로 만들어놓은 고유한 id 활용
      <div>
        {diaryList.map((it)=>(
           <div key={it.id}> // 자식 아이템의 가장 최상위 태그에 key prop 작성
             <div>작성자 : {it.author}</div>
             <div>일기 : {it.content}</div>
             <div>감정 : {it.emotion}</div>
             <div>작성 시간(ms) : {it.create_date}</div>
           </div>
        ))}
      </div>

☑️ 만약 고유한 아이디가 없을 경우 map 내장 함수의 콜백 함수에 두번째 파라미터인 index 사용해서 전달하기

  • 단, 배열의 index를 사용할 경우 key로 데이터를 수정/삭제/추가 시 index의 순서가 바뀔 수 있어 문제가 생길 수 있기 때문에 고유한 id를 지정하는 게 현명한 방법
      <div>
        {diaryList.map((it, idx)=>( // idx 몇번째 요소를 순회하고 있는지 가리킴
           // s : DiaryItem
           <div key={idx}> 
             <div>작성자 : {it.author}</div>
             <div>일기 : {it.content}</div>
             <div>감정 : {it.emotion}</div>
             <div>작성 시간(ms) : {it.create_date}</div>
           </div>
           // e : DiaryItem
        ))}
      </div>

☑️ 별도의 컴포넌트로 분할

  • 일기 item을 삭제하거나 수정할 수도 있기 때문에 하나의 컴포넌트로만 쓰게 되면 수정/삭제하는 기능까지 전부 한 곳에 모이기 때문에 별도로 DiaryList 배열 데이터를 사용해서 렌더링하는 DiaryItem이라는 컴포넌트를 분할해주기

  • src/DiaryList.js (import)

import DiaryItem from './DiaryItem.js';
      <div>
        {diaryList.map((it)=>(
			<DiaryItem key={it.id} {...it} /> 
 	       // 데이터를 받아서 렌더링하는 요소
           // 리스트의 아이템이므로 key를 id로 전달
           // 스프레드 연산자를 통해서 일기 하나 객체에 포함된 모든 데이터를 전달
        ))}
      </div>
  • src/DiaryItem.js 생성
const DiaryItem = ({ id, author, content, emotion, created_date }) => {
  return (
    <div className="DiaryItem">
      <div className="info">
        <span className="author_info">
          | 작성자 : {author} | 감정점수 : {emotion} |
        </span>
        <br />
        <span className="date">{new Date(created_date).toLocaleString()}</span>
        // new Date로 created_date 객체 생성
        // toLocalString()로 시간 ms 변환
      </div>
      <div className="content">{content}</div>
    </div>
  );
};

export default DiaryItem;

☑️ CSS Styling

/* List */
.DiaryList { border:1px solid #aaa; padding:20px; margin:20px 0 0 0; }
.DiaryList h2 { text-align:center; }

/* Item */
.DiaryItem { background-color:rgb(240,240,240);margin:0 0 10px 0;padding:20px; }
.DiaryItem .info { border-bottom:1px solid #aaa;margin:0 0 10px 0;padding:0 0 10px 0;}
.DiaryItem .date { color:#aaa; }
.DiaryItem .content { font-weight:600;margin:30px 0; }

📌 정리

  • DiaryList 컴포넌트 생성
  • DiaryList 컴포넌트에서 배열을 Prop으로 전달
  • Map 내장 함수를 사용해서 list 형태로 렌더링
  • 렌더링된 item을 별도의 컴포넌트인 DairyItem으로 분리
profile
필요한 내용을 공부하고 저장합니다.

0개의 댓글