우선 firebase 연동하기 전에, react 감을 익히기 위해서 아래 이슈를 처리하기로 했다.
view components를 작성해주세요.
달력 컴포넌트
-운동추가 컴포넌트에서 날짜와 진행한 운동을 추가해주면, 그 날짜에 운동을 진행했는지 구별해주는 달력 컴포넌트 를 작성.그 날짜에 어떤 운동을 했는지는, 그 날짜를 클릭하여 운동추가 컴포넌트로 넘어갈 수 있도록 하면 될듯.
-CSS, firebase DB 연동은 지금 하지 않아도 괜찮음.
운동추가 컴포넌트
-운동 리스트 컴포넌트에 기록될 운동을 추가해주는 컴포넌트를 작성할 것.
-CSS, firebase DB 연동은 지금 하지 않아도 괜찮음.
간단한 기능을 갖춘 틀을 작성해준다고 생각하면 될 것 같습니다.
이후 세부기능 및 디테일은 다음에 추가하면 됩니다.
역할 분배, 컴포넌트명, 질문 및 추가사항은 comment 달아주세요.
https://github.com/kth990303/WorkOutDiary/issues/7
나는 이번에 데이터가 주어지면, 그 데이터들을 출력해주는 역할을 맡았다.
데이터는 우선은 아래 형식과 같다.
아이디, 날짜, 그날 한 운동목록을 배열로 받는 데이터로 하였다.
다만, 이 부분은 이후 설계에 따라 날짜에 따른 id 부여가 아닌, 운동에 따른 id 부여로 바뀔 수도 있다.
toLocaleDateString() 형식으로 format하는 것이 가장 깔끔하게 나타내주는 것 같아 이용하였다.
toLocaleDateString()을 이용하면 2021-09-24 날짜가 아래와 같이 깔끔하게 표기된다.
단순히 toString()으로 하면 아래와 같이 출력돼 가독성이 떨어진다.
App.js
import './App.css';
import React from 'react';
import WorkListCalender from './components/workListCalender';
function App() {
return (
<WorkListCalender />
);
}
export default App;
먼저 App.js를 위와 같이 변경하였다.
로그인에 성공할 경우 가장 먼저 띄워줄 것이 유저의 이번달 운동기록이기 때문이다.
WorkListCalender 컴포넌트가 내가 작업하는 운동달력 컴포넌트이다.
WorkListCalendar 컴포넌트
function WorkListCalender(props){
const works=[
// 데이터
];
return(
<div className="WorkListCalendar">
<BrowserRouter>
<div>
<h1>운동일지 다이어리</h1>
</div>
<div className="AddWork">
<Link to="/add" className="add">추가</Link>
<Switch>
<Route path="/add" component={AddTodayExercise} />
</Switch>
</div>
</BrowserRouter>
<hr></hr>
<div className="Calendar">
{
works.map(work=>(
<Work work={work}></Work>
))
}
</div>
</div>
)
}
export default WorkListCalender;
이제 위 코드를 하나하나 뜯어보겠다.
먼저, "/add" api 주소로 이동하면 AddTodayExercise 컴포넌트 링크로 이동할 수 있도록 react-router-dom을 이용해 아래 코드를 작성하였다.
<BrowserRouter>
<div>
<h1>운동일지 다이어리</h1>
</div>
<div className="AddWork">
<Link to="/add" className="add">추가</Link>
<Switch>
<Route path="/add" component={AddTodayExercise} />
</Switch>
</div>
</BrowserRouter>
add로 갈 수 있는 링크를 생성해주었고,
그 링크를 클릭하여 add로 이동할 경우 Route로 AddTodayExercise 컴포넌트를 띄우게 해주었다.
<div className="Calendar">
{
works.map(work=>(
<Work work={work}></Work>
))
}
</div>
그 다음으로, 데이터들을 출력해주기 위해서 위와 같이 map을 이용하여 Work컴포넌트로 works 데이터들을 반환하여 출력해주도록 하였다.
참고로, 위의 <BrowserRouter>과 지금의 <div> 코드를 묶어주는 <div className="WorkListCalendar"> 태그 안에 작성해준 것이다.
Work 컴포넌트
사실 이 컴포넌트에서 삽질을 되게 많이 했다.
특정 날짜에 한 운동 목록을 나타내는 배열인 workName을 어떻게 출력해야할지 고민을 되게 많이 했다.
return 렌더링 내에서 map을 쓰는 방법을 몰랐기 때문에, 처음에는 아래와 같이 코드를 썼었다.
function Work({work}){
return(
<div>
<h3>{work.date} 운동일지</h3>
<li>{work.workName[0]}</li>
<li>{work.workName[1]}</li>
<li>{work.workName[2]}</li>
</div>
)
}
그러나, 이렇게 하면 동적배열을 출력해주기 위해선 일일이 배열의 크기만큼 html 코드를 작성해야 한다는 큰 단점이 존재한다.
처음엔 객체 안에 배열을 출력하는 것이다보니, map 안에 map을 써서 출력하게 하는 방법도 사용해봤고 별 방법을 다해봤다.
function TodayWorks({todayWorkNames}){
todayWorkNames.map(todayWorks => <li>{todayWorks}</li>)
}
function Work({work}){
return(
<div>
<h3>{work.date} 운동일지</h3>
<TodayWorks todayWorkNames={work.workName}></TodayWorks>
</div>
)
}
TodayWorks(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
위 코드도 에러가 떴다.
참고로 foreach도 써봤는데, foreach는 map과 다르게 반환을 해주지 않는 void형이어서 쓰기가 참 애매했다.
우리는 map으로 운동 데이터들을 반환해서 렌더링할 수 있도록 해야 했기 때문이다.
위 코드를 Work 컴포넌트 수정 없이 아래의 과정을 거쳐 수정하였다.
- 우선 Work 컴포넌트에서 {}를 이용한 value값 출력이 아닌, TodayWorks 컴포넌트를 호출하는 경우이기 때문에, TodayWorks 컴포넌트에서 return을 이용한 렌더링이 필요할 것이다.
- map은 여러 개의 값을 리턴하므로 <div>태그로 묶어주자.
function TodayWorks({todayWorkNames}){
return(
<div>
{todayWorkNames.map(todayWorks => <li>{todayWorks}</li>)}
</div>
)
}
function Work({work}){
return(
<div>
<h3>{work.date} 운동일지</h3>
<TodayWorks todayWorkNames={work.workName}></TodayWorks>
</div>
)
}
위와 같이 수정하였더니 결과가 아래와 같이 잘 떴다!
아래와 같은 코드도 가능했다.
function TodayWorks({todayWorkNames}){
return <li>{todayWorkNames}</li>;
}
function Work({work}){
return(
<div>
<h3>{work.date} 운동일지</h3>
{work.workName.map(workName=><TodayWorks todayWorkNames={workName}></TodayWorks>)}
</div>
)
}
Work 컴포넌트에서 {}로 동적 value값들을 TodayWorks 컴포넌트 return값으로 출력해주도록 한 것이다.
위 코드를 더욱 더 간단히 할 수 있다.
function Work({work}){
return(
<div>
<h3>{work.date} 운동일지</h3>
{work.workName.map(workName=><li>{workName}</li>)}
</div>
)
}
{}를 이용한 동적 value 값 출력과, {}를 이용하여 map을 return 렌더링 안에서 사용할 수 있다는 점을 새롭게 배웠다.
근데 배우는 과정이 너무 고통스러웠다...
아주 간단한 기능이라 생각했던 것도 이렇게 힘들어했으니 조금 현타가 오긴 한다.
진짜 넘 자유로운 언어다보니 꽤 고통스럽긴 하지만,
오늘의 경험 덕분에 조금이나마 성장했다고 생각하니 만족스럽다.
https://github.com/kth990303/WorkOutDiary/pull/12
덕분에 PR을 날릴 수 있었다.
이제 친구가 작성한 addTodayExercise.js PR도 살펴보고 이해해보는 시간을 가지러 가보겠다.
'JS > 운동일지 다이어리 프로젝트' 카테고리의 다른 글
잠깐 이 프로젝트를 중단하기로 했다. (3) | 2021.10.22 |
---|---|
[210928] 운동 리스트, 그리고 react-datepicker를 이용한 운동 추가 컴포넌트 구현 (0) | 2021.09.29 |
[210923] 디렉토리 구조 세팅, README 추가 (0) | 2021.09.23 |
[210919] React와 Firebase를 연동해보자 (0) | 2021.09.19 |