[React] export, Route, useParam, useEffect, AJAX, 성능관리

import / export

내보낼파일.js 에서 export문으로 함수, 객체, 원시값을 내보냄
다른 파일에서 import 문으로 가져올 수 있음.

  • export named
    여러개 내보낼 수 있다, 단 { 중괄호 } 안에 묶어서 주고받기!
    export한 이름과 동일한 이름으로 import 해야 한다.

    //exportFile.js
    export {myFunction, myVariable};
    //importFile.js
    import {myFunction, myVariable} from './exportFile.js';

  • export default
    한 파일에 하나만 적자!
    해당 파일에서 기본으로 export하기 때문에 import하는 파일에서 자유롭게 네이밍 가능

    //exportFile.js
    export default myFunc
    //importFile.js
    import myFuncName from './exportFile.js';

페이지 이동

상세 주소에 따라 다른 뷰를 보여주는 것
상세 페이지 등 페이지 이동할 때 /이후로 지정
라우터를 사용하면 SPA(Single Page Application)구현
-> 페이지를 이동할때마다 각각의 HTML을 불러와 로딩하는 것이 아닌, 처음에 한번만 받아오고 이후엔 필요한 데이터만 받아와 화면에 보여줌

Route

  • 설치
    npm install react-router-dom

  • index.js

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

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);
  • App.js
    import { Link, Route, Switch } from 'react-router-dom';

🚨A <Route > is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.
💡react-router-dom 라이브러리의 업데이트된 문법을 적용한다. 공식문서
-- > 1. 모든 <Route>를 전체적으로 <Routes>가 감싸줘야한다.

import About from './pages/About';
import Home from './pages/Home';

ReactDOM.render(
  <BrowserRouter>
    <Routes>
      <Route path="/" element={<App />}></Route>
      <Route path="/home" element={<Home />}></Route>
      <Route path="/about" element={<About />}></Route>
    </Routes>
  </BrowserRouter>,
  document.getElementById('root')
);

-- > 2. 파라미터는 element = {<컴포넌트 />}

useParam()

import {useParams} from "react-router-dom";

<Route path="/detail/:id" element={<Detail />}></Route>      

/:id는 url뒤에 아무문자나 받을 수있다. 여기선 id로 작명했지만 아무 이름 가능
/detail/123214과 /detail/2354처럼 무작위 값을 해도 서로 동일 화면
만약 뒤에 오는 값에 따라 다른 화면을 보여주려 한다면??

변수 = useParam();은 url의 모든 파라미터를 저장함

  • Detail.js
    let {id} = useParams();

let id = useParams();하면 console.log(id) >> {id:2} 이런식. destructing 해야함

Link

네비게이션 바에 to속성으로 이동할 페이지 경로를 지정한다.

🚨에러 해결 과정🚨

<Navbar>
  <Nav.Link> <Link to="/">Home</Link> </Nav.Link>
  <Nav.Link> <Link to="/detail">Detail</Link> </Nav.Link>
</Navbar>

이렇게 설정하면
🚨validateDOMNesting(...): <a> cannot appear as a descendant of <a>
💡스택오버플로우 참고 후 <a><a></a></a> 로 인식되는 문제임을 알았고, 하나의 링크태그로 이용해도 된다!

<Navbar>
  <Nav.Link to="/">Home </Nav.Link>
  <Nav.Link to="/about">About </Nav.Link>
</Navbar> 

⚠️index.tsx:30 You rendered descendant <Routes > (or called useRoutes()) at "/" (under <Route path="/" >) but the parent route path has no trailing "". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. Please change the parent <Route path="/" > to <Route path="" >.

이리 저리 찾아봤는데 경고 문구에 다 써있었다 ... !
💡index.js 에서 자식 루트에서 deeper하게 navigate 하려면 처음 자식을 갈 때 * 지정!

<Route path="/*" element={<App />}></Route>

useHistory

window.history와 유사하게 전후나 특정 주소로 이동하게 한다

import { useHistory } from 'react-router-dom';
let history = useHistory();

<button className='bnt-useHistory' onClick={() => { history.goBack( ) }}> 뒤로가기 </button>

<button className='bnt-useHistory' onClick={() => { history.goForward( ) }}> 앞으로가기 </button>

// 특정 링크로
<button className='bnt-useHistory' onClick={() => { history.push('/detail' )}}> 상세페이지로 이동 </button>

Style

SASS

CSS전처리기
선택자의 중첩(Nesting)이나 조건문, 반복문, 다양한 단위(Unit)의 연산 등의 문법 코딩 가능

  • @mixin @include
@mixin 스타일명{
  속성:값;
}

으로 그룹단위 스타일을 변수로 지정해둘 수 있음.
인자를 사용할 수 있다.

mixin fontSize($size) {
  @if $size == 'small' {
    font-size: 10px;
  }

처럼 조건으로 사용할 수도 있고, 속성에 대한 값으로 사용할 수도 있다.
이를 사용할때는

적용할 요소{
  @include 스타일명;
  @inlcude 스타일명(인자);
}

참고

useEffect

deps인자에 따라 페이지가 렌더링 될 때마다 콜백함수를 실행한다.
useEffect(cb,deps);

  • No dependency
useEffect(() => {});

모든 렌더링 발생시마다 발동되기 때문에 유용하진 않음

  • []
useEffect(() => {}, []);

처음 렌더링이 발생한 직후에만 발동. 더이상은 발동 X

  • dependent on a variable
useEffect(() => {}, [prop, state]);

처음 렌더링이 발생한 직후, 그리고 배열 안 변수의 값이 변경될때마다 발동

AJAX

Asynchronous JavaScript And XML : 서버와 비동기적으로 데이터를 주고받는 기술.
"새로고침 없이 서버에 GET요청하는 코드"

axios

npm install axios
import axios from 'axios';

  • GET
axios.get('~~.json')
.then((result) => {
  console.log(result)
})
.catch((error)=>{
  console.log(error)
})

성능향상 / 유지관리

함수나 오브젝트는 변수에 담아 컴포넌트 바깥에 저장해두자

lazy import

App.js에서 처럼 많은 import가 필요할 때, 필요한 컴포넌트만 import하도록 지정
import React, {lazy, Suspense} from 'react';

// 기존 import
// import Detail from './Detail.js';
// lazy import
let Detail = lazy( ()=>{ return import('./Detail.js') } );

//해당 컴포넌트 호출할때
  <Suspense fallback={ <div>로딩중입니다~!</div> }>
    <Detail/>
  </Suspense>

memo

컴포넌트는 관련된 state, props가 변경되면 항상 자동 재렌더링!
부모 컴포넌트의 props가 변경됐을 때 자식 컴포넌트들도 재렌더링 되는데...
속도 저하 등 문제가 있기 때문에!
import React, { memo} from 'react';

function Cart(){
  return (
    <Parent 이름="존박" 나이="20"/>
  )
}

function Parent(props){
  return (
    <div>
      <Child1 이름={props.이름}/>
      <Child2 나이={props.나이}/>
    </div>
  )
}
function Child1(){
  useEffect( ()=>{ console.log('렌더링됨1') } );
  return <div>1111</div>
}
let Child2 = memo(function(){
  useEffect( ()=>{ console.log('렌더링됨2') } );
  return <div>2222</div>
})

Child1에서 '이름'을 변경해도 Child2에서 '나이'는 관련없기때문에 재렌더링 되지 않음!
컴포넌트가 너무 크거나 잦은 재렌더링을 막을 때 사용
하지만 기존과 바뀐 걸 비교하는 연산이 추가되서 props가 크고 복잡하면 부담이긴 하다.

좋은 웹페이지 즐겨찾기