- Node.js 설치
- Create-React-App 혹은 vite 프로젝트 설치
2-1. 그런데 난vite
를 이용할 것이기 때문에
만약create-react-app
이 아니라 vite를 이용하고 싶다면 node 창에서
npm create vite
를 입력한 후 폴더 이름을 생성해주고 React를 선택해주면 프로젝트가 생성된다.
생성된 폴더를 vscode에서 열어주고 터미널에서npm install
로 패키지를 실행한다.
npm run dev을 터미널에 입력해주면 아래처럼 성공한다.
2-2.Create-React-App
프로젝트 설치
vscode 터미널에서npx-create-react-app [프로젝트이름]
- 터미널에서
npm start
를 입력해주면 브라우저가 열리고 리액트 아이콘이 돌아가는 기본 데모웹이 실행된다.
소스코드 파일을 보면,
1. 하나의 html,css 파일
2. App.jsx
3. main.jsx
4. pakage.json / lock
5. git ignore
6. vite config
하나의 html
파일로 동작함.main.jsx
파일. 즉, Node.js 애플리케이션 자체를 만드는 프로젝트가 아닌 프로젝트에서 패키지 관리를 위해 이용한다. 다시 말해서 package.json에 어떤 외부파일에 의존할건지 결정된다. 리액트 라이브러리는 react react-dom 두개가 전부.
그리고 import를 하고나서 ReactDOM으로 시작함. 해석해보자면 root라는 id를 갖고 있는 html 파일의 요소들을 render하라는 이야기. 무엇을? 아래의 코드들을.
- App 컴포넌트 하나만 렌더링 됨.
- 리액트는 결국 이 컴포넌트의 모음집.
- jsx, 동적 표현.
-사용자가 만든 커스텀 컴포넌트들은 jsx 코드를 반환하고, 동적 표현식은 중괄호로 표현- main.jsx 가 렌더링 하고, 상위 컴포넌트 하나만 반환해야함.
- props : 값전달을 위해 사용. 안에 객체, 함수 전부 전달 가능함.
- css 규칙 1 :
.module.css
classes
라는 이름으로 import- css 규칙 2 : jsx 코드에선 css에 접근하기 위해
className
사용
useState
,useEffect
등등
✍ 좌측이 수정전 우측이 수정 후 PostList.jsx
역할 :
목적 :
TC 프로젝트 5번 일지 포스팅 참고. 길어서 링크로 남김.
간단한 백엔드 api와 통신해서 데이터를 보내고, 혹은 데이터를 가져오는 작업.
const express = require('express');
const bodyParser = require('body-parser');
const { getStoredPosts, storePosts } = require('./data/posts');
const app = express();
app.use(bodyParser.json());
app.use((req, res, next) => {
// Attach CORS headers
// Required when using a detached backend (that runs on a different domain)
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,POST');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
next();
});
app.get('/posts', async (req, res) => {
const storedPosts = await getStoredPosts();
// await new Promise((resolve, reject) => setTimeout(() => resolve(), 1500));
res.json({ posts: storedPosts });
});
app.get('/posts/:id', async (req, res) => {
const storedPosts = await getStoredPosts();
const post = storedPosts.find((post) => post.id === req.params.id);
res.json({ post });
});
app.post('/posts', async (req, res) => {
const existingPosts = await getStoredPosts();
const postData = req.body;
const newPost = {
...postData,
id: Math.random().toString(),
};
const updatedPosts = [newPost, ...existingPosts];
await storePosts(updatedPosts);
res.status(201).json({ message: 'Stored new post.', post: newPost });
});
app.listen(8080);
useEffect 라는 훅을 이용해 데이터를 비동기적으로 가져올때 이용함.
이유 : 서버 상황에따라 데이터를 가져오는데 시간이 많이 걸리는 경우가 많음.
단점 : 남용하면 코드 유지보수 불가능에 가까워짐. 꼭 필요한, 개발자들이 정해놓은 경우에만 사용.
- 여러 경로를 정의해 여러 페이지를 로드하고 해당 경로에서 다른 컴포넌트를 로드하기 위해 사용. 대부분의 앱에는 라우팅이 필요함.
- 해당 url 마다 공유할 수 있는 수단
✍main.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import App from "./App";
import NewPost from "./components/NewPost";
import "./index.css";
const router = createBrowserRouter([
{
path: "/",
element: <App />,
},
{
path: "/create-post",
element: <NewPost />,
},
]);
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
);
✍main.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import App from "./App";
import NewPost from "./components/NewPost";
import RootLayout from "./routes/RootLayout";
import "./index.css";
const router = createBrowserRouter([
{
path: "/",
element: <RootLayout />,
chlidren: [
{
path: "/",
element: <App />,
},
{
path: "/create-post",
element: <NewPost />,
},
],
},
]);
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
);
✍ PostList.jsx (frontend project)
useEffect(() => {
async function fetchPosts() {
setIsFetching(true);
const response = await fetch("http://localhost:8080/posts");
const resData = await response.json();
if (!response.ok) {
<div style={{ textAlign: "center", color: "white" }}>
<p>응답이 비정상적입니다...</p>
</div>;
}
setPosts(resData.posts);
setIsFetching(false);
}
fetchPosts();
}, []);