본문 바로가기

프론트엔드/리액트

[리액트] 초기세팅 및 실습 4차

[참고]

상세 실습 내용은 노션 프론트 페이지 실습란 참고

1. react-router-dom 도큐먼트 reactrouter.com/web/guides/quick-start

 

React Router: Declarative Routing for React

Learn once, Route Anywhere

reactrouter.com

2. 생활코딩 -  리액트 라우터 youtu.be/WLdbsl9UwDc

3. Minjun Kim  -리액트 라우터 v4 강의 사용법 알아보기 youtu.be/o6j8zi5mFIg

4. gradient css cssgradient.io/

 

[결과물]

 

코드 : github.com/GoldK11/React/tree/main/practice/simplePage

 

GoldK11/React

React self-study . Contribute to GoldK11/React development by creating an account on GitHub.

github.com


[구조]

이전 버전 :

변경사항 : 

App - <router> Header, Contents</router>

MainPage => Contents

Contents => List

Home, Login, Mypage 추가

 

 

 

 

[state]

setState의 비동기 처리에 주의하자

setState 내에서 이전 state값을 참조하고 싶다면 this.state로 접근하지 말고 반드시 내부 function call을 통해 인자로 전달받은 state를 이용할 것

ko.reactjs.org/docs/faq-state.html

 

컴포넌트 State – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

 

[ajax]

호출은 componentDidMount 훅에서

(호출 후 로컬 state의 초기값을 채운 상태로 컴포넌트가 렌더링 됨)

ko.reactjs.org/docs/faq-ajax.html

 

AJAX 와 APIs – React

A JavaScript library for building user interfaces

ko.reactjs.org

 


 

[react router dom]

1. 설치

npm install react-router-dom

 

2. BrowserRouter와 Route

import {BrowserRouter as Router, Route} from 'react-route-dom';

BrowserRouter : 최상위 컴포넌트를 감싸줘서 그 이하의 모든 컴포넌트에서 라우터를 사용 할 수 있게 함

※ 보통 Router로 리네이밍해서 import 해온다   

BrowserRouter 컴포넌트의 자식 컴포넌트는 무조건 하나여야 함 (하나의 <div> 태그 안으로 넣어주자)

Route : 라우팅 할 각각의 컴포넌트를 감싸줌

 

3. 사용방법

컴포넌트를 직접 감싸거나 component 인자로 전달

import Home from './Home';

// 1. 직접 감싸기
<Route path="/"><Home></Home></Route>

2. component 인자로 전달
<Route path="/" component={Home}></Route>

 

 

 

[route path 설정]

잘못된 사용

<Route path="/"><Home></Home></Route>
<Route path= "/page"><Page></Page></Route>

이렇게 설정할 경우 "www.도메인/page"로 접속했을 때 page만 라우터에 걸리는 게 아니라

path가 "/"로 설정된 home까지 함께 걸린다

 

해결방안 

① exact 

path가 정확하게 일치하는 경우만 매칭

<Route exact path="/"><Home></Home></Route>
<Route path= "/page"><Page></Page></Route>

 

② switch

import {Switch} from 'react-route-dom';

<Switch></Switch> 컴포넌트로 감쌈

하나라도 라우터에 걸리는 컴포넌트를 발견하면 그 컴포넌트만 보여주고 그 아래에 적힌 컴포넌트는 다 무시함

<Switch> 
	<Route path= "/page"><Page></Page></Route>
	<Route path="/"><Home></Home></Route>
</Switch>

 

응용

NotFound  컴포넌트를 만들어 path="*"를에 매핑시키고 Switch 컴포넌트로 감싼 내부의 가장 마지막에 놓으면?

 > 모든 잘못된 url 접근 시 not found 컴포넌트로 보내준다

<Switch> 
	<Route path= "/page"><Page></Page></Route>
	<Route exact path="/"><Home></Home></Route>
	<Route path="*"><NotFound></NotFound></Route>
</Switch>

 

 

 

[Link 컴포넌트]

import {Link} from 'react-route-dom';

 

<a>태그 대신 Link 컴포넌트 사용할 것

<Link to="/page">Page</Link>

 

- 라우트 이동시 페이지 리로드 방지!

- exact 사용 가능

advacned 버전 NavLink 컴포넌트

 : 현재 위치하는 라우터의 링크 컴포넌트에 active 클래스를 추가해줌

import {NavLink} from 'react-route-dom';

 

 

 

[useParams]

url 파라미터 전달하기

:[파라미터 이름] 으로 전달

// App.js
<Route path ="/page/:pageNo"><SubPage></SubPage></Route>

 

파라미터 사용하기

 useParams(); 으로 추출해 사용

import {useParams} from 'react-route-dom';

const SubPage = () => {
	let {pageNo} = useParams();
//	let pageNo = useParams().pageNo;

	return (
    	<div>
        	{pageNo}
        </div>
    )
}

 파라미터로 match 를 전달받아 사용

// SubPage.js

// 1. function 형태
const SubPage = (match) => {
	return (
    	<div>
        	{match.params.pageNo}
        </div>
    )
}


// 2. class 형태
class SubPage extends React.Component {
	render(){
    	return  (
        	<div>
        		{this.props.match.params.pageNo}
        	</div>
        )
    }
}

 

 

[Redirect]

import {Redirect} from 'react-route-dom';

사용하기

// App.js

let loggedIn = true;

return (
	<div>
    	{loggedIn ? <Redirect to="/Mypage" /> : <Loggin />}
    </div>
)

 

 

[useLocation]

현재 location 정보를 가져옴

import { useLocation } from 'react-router-dom';

let location  = useLocation().pathname
console.log(location); // /pathname

파일 업로드

codesandbox.io/s/vj1q68zm25?file=/src/ImageUpload.js

 

Material UI Image Upload Component - CodeSandbox

Material UI Image Upload Component by ramongduraes using @material-ui/core, @material-ui/icons, base64-img, image-to-base64, prop-types, react, react-dom, react-swipeable-views

codesandbox.io

gaemi606.tistory.com/39

 

React | 이미지 업로드 후 미리보기 (on Change / image preview)

1. constructor(생성자)를 이용해 state 생성 file은 input type='file'에 들어온 파일 값을 넣고, URL은 이미지 미리보기(preview)를 보여주기 위한 값입니다. URL은 img태그의 src값에 들어감 constructor(props..

gaemi606.tistory.com

 

 

[함수형 컴포넌트와 훅]

1. 구조분해 할당을 통한 sate와 setter 매핑

참고

react.vlpt.us/basic/07-useState.html

 

7. useState 를 통해 컴포넌트에서 바뀌는 값 관리하기 · GitBook

7. useState 를 통해 컴포넌트에서 바뀌는 값 관리하기 지금까지 우리가 리액트 컴포넌트를 만들 때는, 동적인 부분이 하나도 없었습니다. 값이 바뀌는 일이 없었죠. 이번에는 컴포넌트에서 보여줘

react.vlpt.us

import React, { useState } from 'react';

const [number, setNumber] = useState(0);

 

리액트의 useSate로 

state에서 관리될 변수 number와 초기값,

스테이트 변경에 사용될 메서드 setNumber를 매핑함

 

useStaate()의 리턴값 중 첫번째는 state 변수, 두번째는 setter 함수를 지칭

파라미터로는 state 변수의 초기값으로 들어간다.

 

 

[findDOMNode is deprecated in StrictMode]

create-react-app 으로 리액트 어플리케이션을 생성하면 개발 모드에서 자동으로 StrictMode가 적용되게 된다.

당장 구동에는 이상이 없어도 리액트 친화적이지 않거나 에러 위험성을 내포하는 코드를 잡아준다.

 

material ui의 popover 컴포넌트를 사용하다가 발견한 이 에러도 스트릭 모드이기에 잡아주는 것.

그냥 무시해도 되지만 이왕이면 정확하게 하는게 좋을것 같아서 고칠 방법을 찾아봤으나

 

기존 버튼 클릭 함수에서 이벤트 객체의 currentTarget을 찍어서 Popover 컴포넌트의 anchorEl 요소에 매핑해주는 방식에서 에러가 났기 때문에 

    handleClick = (e) => {
        this.setState({ anchor: e.currentTarget })
    }
<Popover
    id={this.props.id}
    open={this.props.anchor ? true : false}
    anchorEl={this.props.anchor}
    onClose={this.props.onClose}
    anchorOrigin={{
        vertical: 'bottom',
        horizontal: 'center',
    }}
    transformOrigin={{
        vertical: 'top',
        horizontal: 'center'
    }}
>
    팝오버
</Popover>

 

리액트 권장사항인 createRef를 이용해 DOM 노드를 감싸는 래퍼를 만들어 ref를 대신 매핑해 주었다.

<HelpIcon className="RoundButtonDarken" onClick={this.handleClick} ref={this.myRef} />


    handleClick = () => {
        console.log('handleClick', this.myRef);
        this.setState({ anchor: this.myRef })
    }
<Popover
    id={this.props.id}
    open={this.props.anchor ? true : false}
    anchorEl={this.props.anchor}
    onClose={this.props.onClose}
    anchorOrigin={{
        vertical: 'bottom',
        horizontal: 'center',
    }}
    transformOrigin={{
        vertical: 'top',
        horizontal: 'center'
    }}
>
    팝오버
</Popover>

 

근데 material ui 의 anchorEl 이 ref형을 받질 않음ㅋㅋ

결국 anchorEl 에 html 태그를 넣어주는 수 밖에 없어서 수정 실패...ㅅㄱ..

 

 

예전에 Vue를 사용했을 때도 그렇고 virtual DOM 특성상 DOM엘리먼트에 직접 접근하고 제어하는 것을 지양하는 듯 하다.

 

 

참고

ko.reactjs.org/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage

 

Strict 모드 – React

A JavaScript library for building user interfaces

ko.reactjs.org