블로깅 주제
- 나만의 아고라 스테이츠 만들기 - 서버 & 리액트 리팩토링
1. 지금 현재, 당신의 기분이나 느낌을 표현해 주세요.
- 역시 솔로프로젝트는 뭐든 정신이 없다! 리액트로 리팩토링을 꼭 해보고싶었는데... 아직 리액트가 익숙치 않아서 그런가 시작하기가 어렵다.. 그래도 꼭 해내고싶다! 섹션2까지 고생한 나 자신... 멋지다^^
2. 오늘 무엇을 학습한 내용 중 지금 떠올릴 수 있는 단어를 모두 나열해 주세요.
- 나만의 아고라 스테이츠 만들기 - 서버 & 리액트 리팩토링
3. 2에서 작성한 단어를 가지고, 오늘의 학습 내용을 설명해 보세요.
- 솔로 프로젝트 : 나만의 아고라 스테이츠 만들기 - 서버 & 리액트 리팩토링
헤매여서 시간을 쏟은 부분을 정리해보자.
※ params로 받아온 데이터의 value 값은 string 이다!
findById: (req, res) => {
// TODO: 요청으로 들어온 id와 일치하는 discussion을 응답합니다.
const { id } = req.params; // id의 타입 : string
let filteredDiscussion = discussionsData.filter((discussion) => {
return discussion.id === Number(id); // Number 형태로 바꿔서 비교해야 함
})
if(filteredDiscussion.length !== 0){
return res.status(200).send(filteredDiscussion[0]);
}else{
return res.status(404).send('Not Found!');
}
}
※ res.send()와 res.json()의 차이
body 데이터가 배열 또는 객체라면 자동으로 컨텐트 타입을 json 형태로 설정하여,
JSON.stringfy 처리를 하지 않아도 자동으로 json 형태로 응답을 보낸다.
https://fansor.tistory.com/m/15
app.js
const express = require('express');
const app = express();
const cors = require('cors');
const morgan = require('morgan');
// morgan 미들웨어가 세팅되어 있습니다.
// HTTP 요청 logger를 편리하게 사용할 수 있는 미들웨어 입니다.
app.use(morgan('tiny'));
// TODO: cors를 적용합니다.
app.use(cors());
// TODO: Express 내장 미들웨어인 express.json()을 적용합니다.
app.use(express.json());
const port = 4000;
const discussionsRouter = require('./router/discussions');
// TODO: app.use()를 활용하여 /discussions 경로로 라우팅합니다.
app.use('/discussions',discussionsRouter);
app.get('/', (req, res) => {
// 서버 상태 확인을 위해 상태 코드 200과 함께 응답을 보냅니다.
res.status(200).send('fe-sprint-my-agora-states-server');
});
const server = app.listen(port, () => {
console.log(`[RUN] My Agora States Server... | http://localhost:${port}`);
});
module.exports.app = app;
module.exports.server = server;
discussions.js
// TODO: discussions 라우터를 완성합니다.
const { discussionsController } = require('../controller');
const { findAll, findById } = discussionsController;
const express = require('express');
const router = express.Router();
// TODO: 모든 discussions 목록을 조회하는 라우터를 작성합니다.
router.get('/',findAll);
// TODO: :id에 맞는 discussion을 조회하는 라우터를 작성합니다.
router.get('/:id',findById);
module.exports = router;
index.js
const { agoraStatesDiscussions } = require("../repository/discussions");
const discussionsData = agoraStatesDiscussions;
const discussionsController = {
findAll: (req, res) => {
// TODO: 모든 discussions 목록을 응답합니다.
return res.status(200).send(discussionsData);
},
findById: (req, res) => {
// TODO: 요청으로 들어온 id와 일치하는 discussion을 응답합니다.
const { id } = req.params;//string
let filteredDiscussion = discussionsData.filter((discussion) => {
return discussion.id === Number(id);
})
if(filteredDiscussion.length !== 0){
return res.status(200).send(filteredDiscussion[0]);
}else{
return res.status(404).send('Not Found!');
}
}
};
module.exports = {
discussionsController,
};
섹션1에서 만들었던 나만의 아고라스테이츠와 연동!
script.js 하단에
fetch('http://localhost:4000/discussions')
.then(res => res.json())
.then(discussions => {
agoraStatesDiscussions = discussions;
// console.log(agoraStatesDiscussions);
const ul = document.querySelector("ul.discussions__container");
render(ul);
})
이 코드를 추가한 후, 상단에 agoraStatesDiscussions을 선언해준다.
let agoraStatesDiscussions;
리액트로 리팩토링 해보기
리액트는 npm start를 해야 프로젝트가 열리는데... 난 계속 index.html 파일을 열어서 흰 화면만 보였던 것이였다...
이 문제로 어제, 오늘 총 이틀을 삽질을 했다는게 믿기지가 않는다^^ 진짜 나는 바보인가?? 왜 헷갈린거지...
어쨌든 우연찮게 다시 깨닫게 되어 다행이다 ㅠㅠ
리액트로 리팩토링하는 과정을 간단히 살펴보자.
1. 컴포넌트 별로 기능 나누기
2. 섹션1에서 사용했던 파일 컴포넌트 별로 나눠 코드 작성하기(컴포넌트 총 세 개)
3. 서버로부터 데이터 받아오기(useEffect)
App.js
function App() {
const [discussions, setDiscussions] = useState([]);
useEffect(() => {
fetch('http://localhost:4000/discussions')
.then(res => res.json())
.then(data => {
setDiscussions(data);
})
}, []);
return (
<div>
<Form />
<Discussions discussions={discussions}></Discussions>
</div>
);
}
리팩토링의 꽃... useEffect 부분을 다시 보자.
fetch를 통해 '나만의 아고라 스테이츠 만들기 - 서버' 프로젝트에서 만든 서버를 가지고 온다.
discussions는 변하는 데이터이므로 state로 설정 후, 타 리소스에서 가져오는 데이터이므로 useEffect를 사용해준다.
처음 렌더링될 때만 데이터를 받아오면 되므로, dependency array에 []을 넣어준다.
Discussions 컨테이너에 props(props 이름: discussions)로 state 데이터인 discussions를 보내준다.
Discussions.js
export const Discussions = ({discussions}) => {
return <section className="discussion__wrapper">
<ul className="discussions__container">
{discussions.map(discussion => {
return <Discussion discussion={discussion} key={discussion.id} ></Discussion>
})}
</ul>
</section>
}
map을 사용해 데이터를 뿌려주는 컨테이너이다.
Discussion 컨테이너에 props로 배열 안에 있는 요소 하나하나들을 보내준다. 이때 key 값은 discussion의 id값을 사용한다.
Discussion.js
export const Discussion = ({discussion}) => {
const {url, author, avatarUrl, title, createdAt, answer} = discussion;
return (
<li class="discussion__container">
<div class="discussion__avatar--wrapper">
<img class="discussion__avatar--image" src={avatarUrl} alt={`avatar of ${author}`}/>
</div>
<div class="discussion__content">
<h2 class="discussion__title"><a href={url}>{title}</a></h2>
<div className="discussion__information">{`${author} / ${new Date(createdAt).toLocaleString()}`}</div>
</div>
<div class="discussion__answered"><p className="discussion__isAnswered">{answer ?'☑' : '☒' }</p></div>
</li>
);
}
props로 받아온 데이터를 브라우저에 렌더링해주는 컨테이너이다.
'코드스테이츠 SEB FE 41기 > Section 별 내용 정리' 카테고리의 다른 글
section3/Unit1/ [자료구조/알고리즘] 재귀(10/20) (0) | 2022.10.21 |
---|---|
section3/Unit1/ [자료구조/알고리즘] 재귀(10/19) (0) | 2022.10.20 |
section2/Unit10/[Web Server] 기초(10/14~17) (0) | 2022.10.14 |
section2/Unit10/[Web Server] 기초(10/13) (0) | 2022.10.13 |
section2/unit9/[React] 클라이언트 Ajax 요청(10/12) (0) | 2022.10.12 |