티스토리 뷰

propTypes

propTypes으로 props로 들어올 데이터타입을 검사할 수 있다. isRequierd로 필수 항목도 지정해줄 수 있다. 문자와 숫자 말고도 다양한 타입을 검사할 수 있다.

import PropTypes from 'prop-types';

MyComponent.propTypes = {
  name: PropTypes.string.isRequired, // 필수 항목
  picture: PropTypes.string, // 필수 항목 아님
  score: PropTypes.number.isRequired,
};

참고

 

커스텀 컴포넌트에는 addEventListener를 달 수 없다.

 

length 0

arr.length = 0 이면 리액트는 0을 출력하기 때문에 배열의 길이가 0일때는 출력하지 않을거라면 조건문을 arr.length > 0 으로 해야한다.

 

react의 모든 태그는 self closing이 가능하다.

 

props와 구조분해할당

props는 객체형태로 들어오기 때문에  받아오는 컴포넌트에서 구조분해할당을 할 수 있다. 같은 컴포넌트에 props를 다르게 줘서 여러 번 사용한다면 구조분해할당을 해주고 사용하지 않은 props를 가진 컴포넌트의 해당 props에는 undefined가 할당된다. 그럴 때는 기본 값을 설정해주면 좋다. 또 props에서도 객체의 프로퍼티와 값이 같을 때 한번만 적어줄 수 있다. 

 

useEffect

useEffect는 컴포넌트가 리렌더링 되는 상황을 설정하고 싶을 때 사용한다.

  • API 호출과 같이 한번만 렌더링 하고싶을 때는 빈배열을 두번째 인자로 준다.
// 최초 렌더링 때 한번만 실행 == componentDidMount
useEffect(()=>{
  console.log("only onetime")
},[])

 

  • 특정 state가 바뀌었을때만 렌더를 실행하고 싶을때는 두번째 인자에 그 state값을 적어준다. 
// 특정 state가 바뀌었을 때만 렌더 == componentDidUpdate
const [change, setChange] = useState(false)
useEffect(()=>{
  console.log("Update Change State")
},[change])
  • 조건문을 주면 최초 렌더링 때 실행을 하지 않고 state가 변경되었을 때 작동하게 할 수도 있다.
// 첫 렌더에는 실행되지 않고 keyword의 길이가 5 이상일때 실행
const [keyword, setKeyword] = useState()

useEffect(()=>{
  if (keyword !== "" && keyword.length > 5) {
    console.log("Search Keyword")
  }
},[keyword])

 

  • return 해주는 함수가 componentWillUnmount와 같은 역할을 한다. 이 함수를 cleanUp function이라고 한다.
    컴포넌트가 없어졌을때 분석결과를 보내고 싶을 수 있고(분석 API) 컴포넌트가 없어졌을 때 이벤트리스너를 지우거나 콘솔에 뭔가를 보여주고 싶을 때 사용한다. 하지만 클린업함수는 그렇게 자주 사용되는 편은 아니다.
// cleanUp function : 컴포넌트가 사라질 때 실행되는 함수 == componentWillUnmount
const MyComponent1 = () => {
  useEffect(()=>{
    console.log("show!")
    return () => console.log("hide!") // cleanUp function
  },[])
  return <h1>MyComponent</h1>
}
  • 함수선언을 따로 해서 useEffect의 첫번째 인자로 넣어 줄수도 있지만, useEffect 안에 익명 화살표함수로 작성하는 방법을 더 많이 사용한다. 
// 이렇게보다는
const MyComponent1 = () => {
  const hideFn = () => {
    console.log("hide!")
  }
  const showFn = () => {
    console.log("show!")
    return hideFn;
  }
  useEffect(showFn,[])
  return <h1>MyComponent</h1>
}

// 이렇게 많이 작성한다.
const MyComponent1 = () => {
  useEffect(()=>{
    console.log("show!")
    return () => console.log("hide!")
  },[])
  return <h1>MyComponent</h1>
}

// 익명함수를 쓸 때도 function보다도 화살표함수를 더 많이 사용한다.

 

 

Fetch를 쓰는 더 깔끔한 방법

fetch를 사용할 때 then보다 async await이 더 선호된다.
await을 붙인 fetch를 한번 더 괄호로 감싸주고 await을 2번 사용해 코드를 더 짧게 쓸 수 있다.

Const getSomethings = async () => {
Const json = await ( await fetch(‘url’)).json();
  setState(json.data);
}

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

 

Router

Router를 사용하면 엔드포인트에 따라서 다른 컴포넌트를 렌더할 수 있다. react-dom-router 패키지를 설치해줘야한다.

// 강의에서 나온 구버전
import {BrowserRouter as Router, Switch, Route} from "react-dom-router";
import MyComponent1 from "./MyComponent1";
import MyComponent2 from "./MyComponent2";

function App() {
  return (
    <Router>
      <Switch>
        <Route path="/"> // home
          <MyComponent1 />
        </Route>
        <Route path="page"> // /page
          <MyComponent2 />
        </Route>
      </Switch>
    </Router>
  )
}

 

지금은 버전이 달라져서 Switch가 Routes로 대체되었으며 Routes는 자식태그로 무조건 Route만 가질수 있다. 그렇지 않으면 에러메세지가 발생한다. Route의 자식태그로 넣어준 컴포넌트는 Route의 element 속성에 넣으면 된다.

// 버전업으로 인한 새로운 버전
import {BrowserRouter as Router, Routes, Route} from "react-dom-router";
import MyComponent1 from "./MyComponent1";
import MyComponent2 from "./MyComponent2";

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<MyComponent1 />} />
        <Route path="page" element={<MyComponent2 />} />
      </Routes>
    </Router>
  )
}

 

라우터는 BrowserRouter와 HashRouter가 있다.

BrowserRouter - 우리가 흔히 아는 url
http://localhost/page

HashRouter - url에 #이 붙음
http://localhost/#/page

 

Link

A페이지에서 B페이지로 이동하고 싶을 때 a태그를 쓸수도 있지만 그렇게 실행하면 모든 페이지가 재실행된다. 이럴 때를 위해서 Link라는 컴포넌트가 존재한다. to속성에 엔드포인트를 적어서 사용할 수 있고 import를 하면 어디서든 쓸 수 있다. 

<h2><Link to="/page">{title}</Link></h2>

 

Link를 사용하려면 Router 안에 위치해 있어야한다.

import {BrowserRouter as Router, Routes, Route} from "react-dom-router";
import MyComponent1 from "./MyComponent1";
import MyComponent2 from "./MyComponent2";

// Link 사용 가능
function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<MyComponent1 />} />
        <Route path="page" element={<MyComponent2 />} /> // Link가 있는 컴포넌트
      </Routes>
    </Router>
  )
}
import {BrowserRouter as Router, Routes, Route} from "react-dom-router";
import MyComponent1 from "./MyComponent1";
import MyComponent2 from "./MyComponent2";

// Link 사용 불가능
function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<MyComponent1 />} />
      </Routes>
    </Router>
    <Route path="page" element={<MyComponent2 />} /> // Link가 있는 컴포넌트
  )
}

 

useParams

페이지의 파라미터를 받아올수있다.

// 강의에서 나온 구버전
function App() {
  return (
    <Router>
      <Switch>
        <Route path="/"> // home
          <MyComponent1 />
        </Route>
        <Route path="page/:id"> // page
          <MyComponent2 />
        </Route>
      </Switch>
    </Router>
  )
}

...

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

function MyComponent2() {
  const parameter = useParams()
  return (
    console.log(parameter) // {id : 35252}
  )
}

// 구조분해할당 가능
function MyComponent2() {
  const {id} = useParams()
  return (
    console.log(id) // 35252
  )
}
// 그리고 알아낸 id로 API 호출을 해서 페이지를 구현하면 된다!

 

gh-pages로 배포

gh-pages 설치

npm install --save-dev gh-pages

package.json 수정

package.json 파일에서 마지막에
,하고
"homepage": "https://2021bong.github.io/repo-name"
추가

scripts에서
"deploy" : "gh-pages -d build", // 추가한 홈페이지 경로에 build 폴더를 가져가도록 script
"predeploy" : "npm run build" //  deploy를 실행하면 build 명령어를 실행하도록 하는 script

홈페이지에 배포되기까지 조금 시간이 걸릴 수 있음
그러면 배포 끝!

깃헙페이지로 배포하면 기본 url이 /가 아니기 때문에 BrowserRouter에 basename을 설정해줘야 한다.

const Router = () => {
  return (
    <ThemeProvider theme={theme}>
      <BrowserRouter basename='/레포이름'>
        <Routes>
          <Route path='/' element={<Main />} />
          <Route path='/detail/:id' element={<Detail />} />
        </Routes>
      </BrowserRouter>
    </ThemeProvider>
  );
};

 

컴포넌트의 크기를 동일하게 하기 위해서 보여 줄 글자 수 제한하기

// 글자의 최대길이를 확인해서 설정하기
<p>{summary.length > 30 ? `${summary.slice(0, 30)}...` : summary }</p>

// 단어가 안잘리도록 단어단위로 나누기
<p>{summary.split(" ").length < 10 ? summary : `${summary.split(" ").slice(0, 9).join(" ")}...`}</p>

 

728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
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
글 보관함