React Router Dom

Noa·2022년 12월 1일
0

React

목록 보기
10/22

페이지가 전환될때마다 주소창이 다르다

function App(){
	return(
		<div>
          <h1>React Router DOM example</h1>
          <Home></Home>
          <Topics></Topics>
          <Contact></Contact>
		</div>
	)
		
}

React Router Dom : 여러개의 페이지로 이루어져있는 어플리케이션에서 진정한 가치를 발휘할 수 있다.

리액트 라우터 돔 홈페이지 -> quick start

라우팅, 라우터: 사용자가 어떤 주소로 들어왔을때 그 주소에 해당하는 적당한 페이지를 사용자에게 보내주는 것

BrowserRouter: 리액트 라우터 돔을 적용하고싶은 컴포넌트의 최상위 컴포넌트에 감싸주는 랩퍼 컴퍼넌트 라는 것 , App 이라는 최상위 컴포넌트를 >BrowserRouter>로 감싸준다 => App이라는 컴포넌트 안에서는 이제 browswerRouter를 사용할 수 있는 상태가 되었다.

라우팅의 가장 본질 적인 작업 : url에 따른 적당한 컴포넌트가 (최상위 컴포넌트안의 컴포넌트들)위치하게
->
Route 라는 컴포넌트가 필요
Route>로 Home, Topics, Contact를 각각 감싼다

<div>
    <h1>React Router DOM example</h1>
    <Route><Home></Home></Route>
    <Route><Topics></Topics></Route>
    <Route><Contact></Contact></Route>
</div>

Route에 path 라는 속성을 지정해준다.
사용자가 아무런 path도 지정하지 않고 싶을때는 Home컴포넌트를 라우팅 해주고싶다 :"/"
Home - "/" ,
Topics - "/topics" ,
Contact - "/contact"

<div>
    <h1>React Router DOM example</h1>
    <Route path="/"><Home></Home></Route>
    <Route path="/topics"><Topics></Topics></Route>
    <Route path="/contact"><Contact></Contact></Route>
</div>

url a 태그를 이용 해서 만들기

<div>
    <ul>
      	<li><a href = "/">Home</a></li>
      	<li><a href = "/topics">Topics</a></li>
      	<li><a href = "/contact">Contact</a></li>
      	<Route path="/topics"><Topics></Topics></Route>
    </ul>
  		<h1>React Router DOM example</h1>
    	<Route path="/"><Home></Home></Route>
    	<Route path="/topics"><Topics></Topics></Route>
    	<Route path="/contact"><Contact></Contact></Route>
</div>

http://localhost:3000/
-> path="/"
http://localhost:3000/topics
-> path="/" 애한테도 걸린다
-> path="/topics"

라우터의 사용설명서를 봐라
exact라는 속성을 추가해주면 정확하게 path가 일치할때 매칭을 해준다.
{Route exact path="/topics">

<Route exact path="/topics"><Topics></Topics></Route>

컴포넌트가 깊어져도 어디있던간에 Route path를 지정만해주면 그 컴포넌트는 그 주소와 매칭되는
애가 라우팅 화면에 표시가 된다.
라우트의 패스와 일치하는 컴포넌트는 , 라우트는 어디에 있건, 누구건 화면에 출력된다 => 동적 라우팅

<Route path="/topics"><Topics></Topics></Route>
<Route path="/topics"><Topics></Topics></Route>

topics가 화면에 두번출력

스위치라는 컴포넌트로 감싸면 -> 만약에 exact를 쓰지 않고도 쓴것과 똑같은 효과를 낼 수 있는 방법이 있다
import 해서사용

<div>
    <ul>
      	<li><a href = "/">Home</a></li>
      	<li><a href = "/topics">Topics</a></li>
      	<li><a href = "/contact">Contact</a></li>
      	<Route path="/topics"><Topics></Topics></Route>
    </ul>
  	<Switch>
  		<h1>React Router DOM example</h1>
    	<Route path="/"><Home></Home></Route>
    	<Route path="/topics"><Topics></Topics></Route>
    	<Route path="/contact"><Contact></Contact></Route>
  	</Switch>
</div>

Switch라는 컴포넌트를 이용해서 라우트를 감싸께 되면, React Router Dom은 path 와 일치하는 첫번째 컴포넌트가 발견되면, 나머지 컴포넌트는 버린다.
모든 컴포넌트는 path앞에 exact가 없으면 첫번째 발견된 컴포넌트의 path에 걸린다.

여기서 스위치를 지우면

<Route path="/"><Home></Home></Route>
<Route path="/topics"><Topics></Topics></Route>

topics로가도 둘다 렌더링된다-> /에서 Home이 걸리기 때문에

<Switch>
	<Route path="/topics"><Topics></Topics></Route>
	<Route path="/contact"><Contact></Contact></Route>
	<Route path="/"><Home></Home></Route>
</Switch>   

스위치가 있으면 그 스위치 아래에 일치하는 것(내가 누른것) 하나만 출력, (일치한다는 것이 /topics와 일치한는것에는 / 도포함된다.)
스위치가 없으면 모두 출력

이것을 응용하여 사용자가 존재하지않는 페이지에 대해 입력햇을때 /adfasdfasfdasfdas

<div>
    <ul>
      	<li><a href = "/">Home</a></li>
      	<li><a href = "/topics">Topics</a></li>
      	<li><a href = "/contact">Contact</a></li>
      	<Route path="/topics"><Topics></Topics></Route>
    </ul>
  	<Switch>
  		<h1>React Router DOM example</h1>
    	<Route exact path="/"><Home></Home></Route>
    	<Route path="/topics"><Topics></Topics></Route>
    	<Route path="/contact"><Contact></Contact></Route>
        <Route path="/">Not Found</Route>
  	</Switch>
</div>

사용자가 뭔가 잘못들어왔을때 exact를 뺀 / 를 집어넣어서
어떤 path를 입력하든 /는 걸리기 때문에
Home을 위로 올렸을 때 문제 없게 하려면 exact를 추가하면된다.
그런데 만약에 사용자가 존재하지 않는 페이지로 들어왔을 때 not found 라는 페이지를 보여주고 싶을때

Link라는 컴포넌트
싱클페이지 어플리케이션을 만들고 있는데 여기서 중요한것은 페이지가 리로드 되지 않고 실제 동적으로 가져오는 데이터는 코딩으로 만들거나 ajax와 같은것을 통해서 비동기적으로 데이터를 끌고와서 페이지를 동적으로 만들어주는 것이 굉장히 중요하다

Link 컴포넌트를 이용해서 a href를 Link to로 변경해준다
-> 페이지 전체에 렌더링이 일어나지 않는다 페이지가 리로드 없이

<div>
    <ul>
      	<li><Link to = "/">Home</Link></li>
      	<li><Link to = "/topics">Topics</Link></li>
      	<li><Link to = "/contact">Contact</Link></li>
      	<Route path="/topics"><Topics></Topics></Route>
    </ul>
  	<Switch>
  		<h1>React Router DOM example</h1>
    	<Route exact path="/"><Home></Home></Route>
    	<Route path="/topics"><Topics></Topics></Route>
    	<Route path="/contact"><Contact></Contact></Route>
        <Route path="/">Not Found</Route>
  	</Switch>
</div>
}
ReactDOM.render(<BrowserRouter><App/><BrowserRouter>, document.getElement.getElementById('root))

라우팅과 라우팅을 페이지에 리로드 없이 처리하는 Link를 할줄알면,

서비스하고 있는 웹,앱어플리케이션의 웹서버 세팅이 사용자가 어떤 path로 들어와도 동일한 웹페이지를 서비스 할 수 있어야한다.
=> 안돼는 경우를 위해

Router
HashRouter => BrowserRouter 대신에 넣고 리로드
localhost:3000/ => localhost:3000/#/topics 으로 바뀐다

어떤 경로로 들어와도 root페이지에 있는 Html 파일을 서비스 할 수 있다면, BrowserRouter를 쓰면되고 그게 안된다면 HashRouter를 사용하면 된다.

Navigation or Navlink
링크와 유사한 기능인데 링크에 조금의 기능이 더 부과된 것

<div>
    <ul>
      	<li><Navlink exact to = "/">Home</Navlink></li>
      	<li><Navlink to = "/topics">Topics</Navlink></li>
      	<li><Navlink to = "/contact">Contact</Navlink></li>
      	<Route path="/topics"><Topics></Topics></Route>
    </ul>
  	<Switch>
  		<h1>React Router DOM example</h1>
    	<Route exact path="/"><Home></Home></Route>
    	<Route path="/topics"><Topics></Topics></Route>
    	<Route path="/contact"><Contact></Contact></Route>
        <Route path="/">Not Found</Route>
  	</Switch>
</div>

active 라는 클래스가 생긴다 => class ="active"
Topics를 클릭해도 Home 의 class 가 active 된다. 라우터와 같이 / 는 /topics에도 걸리기 때문에 exact를 추가해준다 => 사용자가 현재 자신이 어떤 페이지에 위치하고 있는지 직관적으로 이해할 수 있게 내비게이션에 사용자가 위치하는 곳을 표시해줄 수 있다.
active 라는 classname으로 표시가 되고 있기 때문에

.active{
	background-color:tomato
	text-decoration:none
}
이런식으로 처리 => 클릭할때마다 사용자가 어디에 있는지를 알려주는 기능 
내부 리스트 

Nested Routing
파라미터 primary components의 예제

function Topics(){
	return (
    	<div>
          <h2> Topics</h2>
          	<ul>
              <li><NavLink to="/topics/1">HTML</NavLink><li>
              <li><NavLink to="/topics/2">JS</NavLink><li>
              <li><NavLink to="/topics/3">REACT</NavLink><li>
          	</ul>
            <Switch>
              <Route path="/topics/1">
               		Html is ...
              </Route>
              <Route path="/topics/2">
               		Js is ...
              </Route>
              <Route path="/topics/3">
               		React is ...
              </Route>
            </Switch>
		</div>
      
    )
}

라우터 안에 라우터가 중첩해서 동작 Topics 안에 위 코드
우리가 갖고있는 페이지가 적으면 이렇게 코딩 할 수 있지만, 적지 않다면 이런식으로 수동으로 하는 것이 별로다. 배열을 하나만들어서 자동으로 리스트가 만들어지고 그에따라서 자동으로 리스트가 만들어지도록 바꿔보자

var contents = [
	{id:1, title:"HTML", description:"HTML is..."},
	{id:2, title:"JS", description:"JS is..."},
	{id:3, title:"REACT", description:"REACT is..."},
	
]

이런식으로 객체를 만든다. 전역변수에 담았다 => 실제 현실에서는 ajax같은 것을 통해서 가져오는 경우가 많다

function Topics(){
	var lis = []
	for(var i=0; i < contents.length;i++){
		lis.push(<li><NavLink to="/topics/"+contents[i].id>{contents[i].id}</NavLink><li>)
      이때의 to의 값은 동적으로 만들어준다. 
	}
	return (
    	<div>
          <h2> Topics</h2>
          	<ul>
              {lis}
          	</ul>
            <Switch>
                <Route path="/topics/1">
                      Html is ...
                </Route>
                <Route path="/topics/2">
                      Js is ...
                </Route>
                <Route path="/topics/3">
                      React is ...
                </Route>
            </Switch>
		</div>
      
    )
}

이전과 똑같이 동작하지만 코드는 훨씨 ㄴ효육적이다 => Route가 많을 필요가 없이 하나의 Route를 갖고 path의 숫자가 무잇이냐에 따라서 그 정보를 가져가서 처리하게 하는 것이 가능하도록

function Topic(){
	var prams = useParams()
	var topic_id = params.topic_id
	var selected_topic = {
		title:"Sorry",
		description:"Not Found"
	
	}
	for(var i=0; i [ contents.length; i ++){
		if(contents[i].id === Number(topic_id)){토픽아이디 값이문자열이라숫자로
			selected_topic = contents[i]
			break
		}
	}
	변수를 하나 만들어서 콘솔찍어보면 topic_id의 정보가 담겨있다. 훅을 이용했다 
	topic_id의 값을 알수 있다
	return (
		<div>
          <h3>{selected_topic.title}</h3>
          {selected_topic.description}
        </div>
	)
}

function Topics(){
	var lis = []
	for(var i=0; i < contents.length;i++){
		lis.push(<li key ={contents[i].id}><NavLink to="/topics/"+contents[i].id>{contents[i].id}</NavLink><li>)
      이때의 to의 값은 동적으로 만들어준다. 
	}
	return (
    	<div>
          <h2> Topics</h2>
          	<ul>
              {lis}
          	</ul>
          	<Route path="/topics/:topic_id">
              	<Topic></Topic>
          	</Route>
 라우트의 path는 토픽스로들어오는 것중에 뒤에 어떠한 값(topic_id)이 있는 애가 들어온다
		 </div>
      
    )
}

topic component가 화면에 출력될때, 우리가 원하는 것은 그 id값에 해당되는 그 contents 배열의 객체를 가져와서 렌더될 컨텐트를 제너레이션 해주는 것이 우리가 하고싶은 일
첫번째로 해줘야 하는 것이 Topic>/Topic> 안에서 topic이 화면에 출력된 이후인 Route의
topic_id 값이 무엇인지를 알아내는 것을 할 줄 알아야한다.

API의 Hook의 useparams 훅을 실행해야한다

server rendering
우리가 만든 어플리케이션은 자바스크립트로 동적으로 만들어지는 어플리케이션이기 때문에 검색엔진과 같은 로봇들은 정적인 html이 없으면 처리할 수 없거나 어렵다
우리가 만들 웹페이지를 서버쪽에서 nodejs 와같은 기술로 생성해서 최종적으로 정적인 html로 만들어준다

code splitting 이라는 것은
우리가 만든 애플리케이션의 페이지가 굉장히 많아지면, 애플리케이션의 용양이 커지고 그 러면 그용양을 우리가 페이ㅏ지를 또는 컴포넌트를 적당히 쪼개서 필요할때마다 로드하게 할 수있다면 성능도 좋아지고 돈도 절약, 여러장점이 생긴다. 우리가 원하는데로 컴포넌트를 쪼개는 테크닉

profile
몰입

0개의 댓글