blog clone-1
리액트를 사용해서 처음하는 프로젝트인 만큼 크게 어려운 개념은 이용하지 않았다
- 리액트의 컴포넌트를 이용해서 최대한 반복되는 부분을 컴포넌트로 작성해서 html작성을 반복하는것을 줄인다
- React Router를 사용해서 한 화면에서 화면 전환이 이루어지게 만들어야한다
클론할 블로그 css부분이나 html부분이 클론에서 중요할 수 있지만 리액트를 처음 사용해보는 것이라 위 두가지 목표를 달성하는게 우선이라 기능을 최우선으로 구현했다
화면 구성 요소를 컴포넌트로 만들고 React-router-dom을 이용해서 각 링크에 해당하는 컴포넌트를 랜더링해야된다
제일먼저 화면에 항상 있는 네비게이션 바를 간단하게 리액트 부트스트랩을 이용해서 구성만 했다
리액트 부트 스트랩 적용하기
yarn add react-bootstrap bootstrap
npm install react-bootstrap bootstrap 터미널에서 두가지중 한가지를 작성해서 부트스트랩을 설치한다
리랙트앱의 src에서 index.js에 **import 'bootstrap/dist/css/bootstrap.css';를 추가하면 부트스트랩 사용준비는 끝난다
네비바 만들기
블로그에 상단에 바가 있어서 비슷한 상단 바를 만들기 위해 부트스트랩에서 찾아서 적용시키자 src에 components 폴더를 만들어 앞으로 만들 컴포넌트를 모았다 components에 TopNav.js를 만들어 저장하고 네비바 컴포넌트를 복사해서 붙여 넣는다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//TopNav.js
import React from 'react';
import Button from 'react-bootstrap/Button';
import Container from 'react-bootstrap/Container';
import Form from 'react-bootstrap/Form';
import Nav from 'react-bootstrap/Nav';
import Navbar from 'react-bootstrap/Navbar';
function TopNav() {
return (
<Navbar bg="light" expand="lg">
<Container fluid>
<Navbar.Brand href="#">brunch</Navbar.Brand>
<Navbar.Toggle aria-controls="navbarScroll" />
<Navbar.Collapse id="navbarScroll">
<Nav
className="me-auto my-2 my-lg-0"
navbarScroll
>
</Nav>
<Form className="d-flex">
<Button variant="outline-success">Search</Button>
</Form>
</Navbar.Collapse>
</Container>
</Navbar>
);
}//필요없는 부분은 지웠다
export default TopNav;
위 파일을 app.js와 연결 시키기 위해 import 경로를 입력하자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//App.js
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import TopNav from "./components/TopNav" //해당 컴포넌트 파일의 위치
const App = () => {
return (
<div className='App'>
<TopNav></TopNav>
</div>
);
}
export default App;
이런식으로 네비바가 생성된다
자신 정보
자신의 이름과 사진 그리고 약간의 설명이 있다 이 부분은 항상 보여지고 아래 메뉴중 선택이 바뀌더라도 이부분은 그대로이다 따라서 아래 보여지는 부분하고 따로 분리해서 만들어야한다는 걸알았다
UserInfo.js components폴더에 파일을 만들고 위와 디자인은 완전히 다르지만 구성은 비슷하게 했다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//UserInfo.js
import React from 'react';
import Image from 'react-bootstrap/Image'
function UserInfo(props) {
return (
<>
<h2>{props.name}</h2>
<Image src= {props.imgPath} roundedCircle width="10%" />
<p>{props.info}</p>
<p>구독자 123</p>
<p>관심작가 26</p>
</>
);
}
export default UserInfo;
여기서 파일을 작성했으니 app.js에 당연히 연결시켜줘야한다
카테고리 선택
부트스트랩에서 Nav중 비슷한걸 골라서 적용했다 Link가 내장되어 있어서 글 카테고리를 누를 때 주소가 바뀌는것을 쉽게 할 수 있었다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import React from 'react';
import UserIntro from "./UserIntro"
import Articles from "./Articles"
import Works from "./Works"
import NotFound from "./NotFound"
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Nav from 'react-bootstrap/Nav';
function Menu(props) {
return (
<BrowserRouter>
<Nav fill variant="tabs" defaultActiveKey="/home">
<Nav.Item>
<Nav.Link href="/info">작가소개</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link href="/articles">글 {props.listArticles.length}</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link href="/works">작품 {props.images.length}</Nav.Link>
</Nav.Item>
</Nav>
<Routes>
<Route path="/" element={<UserIntro tags ={props.tags} name = {props.name}/>}></Route>
<Route path="/info" element={<UserIntro tags ={props.tags} name = {props.name}/>}></Route>
<Route path="/articles" element={<Articles listArticles={props.listArticles}/>}></Route>
<Route path="/works" element={<Works images={props.images}/>}></Route>
<Route path="/*" element={<NotFound />}></Route>
</Routes>
</BrowserRouter>
);
}
export default Menu;
여기서 react-router-dom이 사용된다
Link
<Link to="추가로 붙을 주소">클릭 부분 </Link> Link 컴포넌트를 통해서 현재 주소에 to이하 부분이 주소에 추가된다 여기서는 <Nav.Link></Nav.Link>가 같은 역할을 한다
글을 누르면 주소 뒤에 /articles가 추가로 붙는다
react-router-dom
이 안에는 여러가지가 더있지만 사용한 BrowserRouter, Routes, Route 3가지만 설명하면
<BrowserRouter>는 Html5의 History API(pushState, replaceState, popstate event)를 사용하여 URL과 UI를 동기화 시켜준다
<BrowserRouter>는 리액트 라우터 돔을 적용시킬때 최상단에서 감싸는 컴포넌트라고 이해하고 적용시켰다
<Routers>는 여러 <Router> 를 감싸는데 사용되고 <Router>태그의 path=”이동할경로 뒤 주소”로 현재 경로 + 이동할 경로 뒤 주소를 확인한다
Router 컴포넌트 이용
<Routers>로 묶인 <Router>중에서 조건에 맞는 <Router>컴포넌트를 실행시킨다
<Router path="/경로" element={조건에 맞는 경우 보여줄 컴포넌트}></Router> Link를 통해서 주소를 변경했으면 Router의 path에 맞는 것을 실행한다 이렇게 실행되는 컴포넌트는 그 부분만 렌더링한다
a태그를 이용하지 않는 이유(싱글 페이지 어플리케이션)
a태그를 이용하면 누를때 마다 페이지를 새로 불러오게 된다 따라서 로딩시간이 소요되고 페이지 전체를 로딩해야되서 비효율적이다 그래서 Link로 주소경로를 바꾸고 react-router-dom를 이용해서 조건에 맞는 경로를 찾아 그 부분만 렌더링 시켜 a태그보다 효율적이다
글 목록 보여주기
Link와 Router를 이용해서 보여줄 컴포넌트를 만들어야한다 이 컴포넌트는 카테고리 선택에서 글 or 작품을 누르면 나오는 컴포넌트이다
따라서 <Router path="/경로" element={조건에 맞는 경우 보여줄 컴포넌트}></Router> 중괄호 안에 작성된다 <Articles/>가 들어간다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Articles.js
import React from 'react';
import Card from 'react-bootstrap/Card';
import Col from 'react-bootstrap/Col';
import Row from 'react-bootstrap/Row';
import Button from 'react-bootstrap/Button';
import { useNavigate } from 'react-router-dom';
function Articles(props) {
const navigate = useNavigate();
const posts =[]
for (let i =0; i<props.listArticles.length; i++){
let a = props.listArticles[i];
posts.push(
<Col >
<Card>
<Card.Img variant="top" src={a.src} />
<Card.Body>
<Card.Title>{a.title}</Card.Title>
<Card.Text>{a.preview} </Card.Text>
<Card.Text> <small >{a.createDate}</small></Card.Text>
</Card.Body>
</Card>
</Col>)
}
return (
<>
<Row xs={4} md={2} className="g-4">
{posts}
</Row>
<div className="d-grid gap-2">
<Button variant="secondary" size="lg" onClick={() => navigate(-1)}>
Back
</Button>
</div>
</>
);
}
export default Articles;
리액트 부트스트랩 Card 컴포넌트를 이용했다 글이 여러개이므로 for 문으로 배열 객체를 받아 반복해서 출력할 리스트에 넣어줬다
for 문을 통해서 객체 배열을 처리했는데 다음 글에서 map으로 바꾸고 props에 대해서 설명하겠다

