[React] 1강. Props와 useState

youngseo·2022년 7월 26일
0

REACT

목록 보기
32/52
post-thumbnail

리액트 18버전 업그레이드

커리큘럼

리액트의 작동원리(SPA)

  • 사실은 하나의 HTML파일을 보여주고, 내부의 요소들은 모드 자바스크립트를 활용해서 변경시킵니다.
  • 페이지가 변경될 때마다 무조건 새롭게 html,css파일을 표시했어야했던 예전 방식보다 훨씬 효율적입니다.
  • 단점 : 초기렌더링 과정에 시간이 걸립니다.
  • 리액트는 가상으로 html요소들을 생성하고, 현재 화면에 표시되는 html요소들과 비교를 해 달라진 부분만 다시 그리는 Virtual Dom with Diff Algorithm을 사용합니다.
  • 장점: 페이지의 수가 많아질 수록 그 장점이 더욱 빛나게 됩니다.

컴포넌트

  • React는 compoent를 작성해 조합하는 방식으로 코딩을 진행합니다. 한 컴포넌트 안에 필요한 요소만 따로 html, css, js를 작성합니다.
  • 이 경우 팀으로 하나의 페이지를 작성할 때 요소별로 나눠서 작업할 수 있다는 장점이 있으며, 복잡한 페이지의 코드를 컴포넌트를 통해 조금 더 직관적으로 볼 수 있다는 장점이 있습니다.
  • 함수형과 클래스형 방식이 있습니다.
    • 최근에는 함수형을 쓰는 것이 트렌드이며, 코드 자체도 클래스형을 쓸 때보다 훨씬 짧아집니다.

리액트 css

  • 리액트에서는 class가 아닌 className을 사용합니다.
  • 하지만 실제로는 styled컴포넌트를 활용하기 때문에 className의 사용빈도수가 높지 않습니다.

기타사항

  • 리액트에서의 주석처리는 {/* 주석 */}과 같이 사용합니다.
  • 스니펫: 자주 많이 쓰이는 코드 조각으로 rfce이 있습니다.
  • rfce로 컴포넌트의 기본 코드 구성을 만들수 있습니다.

리액트 프로젝트 시작

$ yarn create react-app firstapp
$ cd firstapp
$ yarn start

Props

  • <First name="노영서" number={5}/>
    • 숫자를 넘기고 싶은 경우 {}를 해줘야합니다.
  • props drilling => 최대한 지양, 가까운 컴포넌트까지만 사용하는 것을 권장합니다.

1. 일반적인 경우

function First({name, number}) {
  return (
    <div>{name} First, 숫자는 {number}</div>
  )
}
  • 명시적일 수 있도록 객체구조분해할당을 해 사용합니다.

2. props가 많은 경우 : 비구조분해할당

  const {name, number} = props
  return (
    <div>{name} First, 숫자는 {number}</div>
  )
  • props가 많은 경우 하나하나 객체구조분해할당을 해줄 수 가 없기 때문에 props로 받아 사용할 객체만 꺼내 쓰는 것도 좋습니다.

3. default 설정

  • 따로 전달하는 props가 없는 경우 default값을 걸어줄 수 있습니다.

방법1

import React from 'react'

function Intro({name="노영서"}) {
  return (
    <>
      <p>{name}</p>
    </>
  )
}

export default Intro

방법2

import React from 'react'

function Intro({name}) {
  return (
    <>
      <p>{name}</p>
    </>
  )
}

Intro.defaultProps = {
  name: '기본 이름'
}

export default Intro

4. props 타입지정

import React from 'react'
import PropTypes from 'prop-types'

function Intro({name}) {
  return (
    <>
      <p>{name}</p>
    </>
  )
}

Intro.propTypes = { //여기는 p가 소문자입니다.
  name: PropTypes.string
}

export default Intro

useState사용

  • 버튼을 눌렀을 때 숫자가 올라가는 로직을 자바스크립트를 통해 작성하는 경우 아래와 같습니다.
import React from 'react'

function Intro({name}) {
  let test = 0
  const countUp = () => {
    test = test + 1
  }
  return (
    <>
      <p>{test}</p>
      <button onClick={countUp} >카운트업!</button>
    </>
  )
}

export default Intro
  • 하지만 위 코드의 경우 버튼을 눌러도 count가 증가하지 않습니다. 리액트는 상태가 변하지 않으면 다시 표시해주지 않기 때문입니다. 이때 사용할 수 있는 useState가 있습니다.
import React, {useState} from 'react'

function Intro() {
  // const [state, setState] = useState(초기값)
  const [test, setTest] = useState(0)

  const countUp = () => {
    setTest(test+1)
  }
  return (
    <>
      <p>{test}</p>
      <button onClick={countUp} >카운트업!</button>
    </>
  )
}

export default Intro
  • 앞으로 리액트에서는 let을 써서 사용하는 경우는 거의 없다고 봐도 좋습니다. 대신, useState를 앞으로 사용하게 될것입니다.

예제: 시간표시

$ yarn add moment moment-timezone
  • moment: 제공된 유틸리티 함수를 사용하여 FullCalendar의 API에서 제공하는 날짜 및 기간을 순간 개체 및 기간으로 변환할 수 있습니다.
  • moment-timezone: 현재시간 뿐만 아니라 다른 나라의 시간도 가져옵니다.

예제1. 우리나라 시간 표시

App.js

import Clock from './components/Clock';

function App() {

  return (
    <div>
      <Clock />
    </div>
  );
}

export default App;

Clock.js

import React from 'react'
import moment from 'moment'

function Clock() {
  return (
    <div>{moment().format('YYYY-MM-DD HH:mm:ss')}</div>
  )
}

export default Clock
  • .format('YYYY-MM-DD HH:mm:ss')를 통해 표시되는 형식을 설정할 수 있습니다.

예제2: 다른나라 시각표시

import React, {useState} from 'react'
import moment from 'moment-timezone'

function Clock() {
  const [time, setTime] = useState(moment().tz('US/Pacific').format('YYYY-MM-DD HH:mm:ss'))
  return (
    <div>{time}</div>
  )
}

export default Clock

예제3: 미국시간 => 한국시간

import React, {useState} from 'react'
import moment from 'moment-timezone'

function Clock() {
  const [time, setTime] = useState(moment().tz('US/Pacific').format('YYYY-MM-DD HH:mm:ss'))
  // 미국시간으로 초기화

  //한국 시간으로 변경하는 함수
  const toSeoul= () => {
    setTime(moment().tz('Asia/Seoul').format('YYYY-MM-DD HH:mm:ss'))
  }
  return (
    <>
    <div>{time}</div>
    <button onClick={toSeoul}>서울로 바꾸기</button>
    </>
  )
}

export default Clock

예제4

서울로 바꾼 후 다시 태평양 시간으로 바꿔주고 싶은 경우 입니다.

  • 이 경우 함수를 하나 더 만들 수도 있지만, 조금 더 효율적으로 작성해보겠습니다.
  • 만약, onClick이벤트에 인자를 전달하고 싶은 경우에는 화살표함수를 이용할 수 있습니다.
import React, {useState} from 'react'
import moment from 'moment-timezone'

function Clock() {
  const [time, setTime] = useState(moment().tz('US/Pacific').format('YYYY-MM-DD HH:mm:ss'))

  const changeTZ = (TZ) => {
    setTime(moment().tz(TZ).format('YYYY-MM-DD HH:mm:ss'))
  }
  return (
    <>
    <div>{time}</div>
    <button onClick={() => changeTZ('Asia/Seoul')}>서울로 바꾸기</button>
    <button onClick={() => changeTZ('US/Pacific')}>미국으로 바꾸기</button>
    </>
  )
}

export default Clock

예제5. props로 timezone을 받아 사용하기

App.js

import Clock from './components/Clock';

function App() {

  return (
    <div>
      <Clock timezone="Asia/Seoul"/>
      <Clock timezone="Asia/Taipei"/>
    </div>
  );
}

export default App;

Clock.js

import React, {useState} from 'react'
import moment from 'moment-timezone'

function Clock(props) {
  const {timezone} = props
  const [time, setTime] = useState(moment().tz(timezone).format('YYYY-MM-DD HH:mm:ss'))

  const changeTZ = (TZ) => {
    setTime(moment().tz(TZ).format('YYYY-MM-DD HH:mm:ss'))
  }
  return (
    <>
    <div>{time}</div>
    <button onClick={() => changeTZ('Asia/Seoul')}>서울로 바꾸기</button>
    <button onClick={() => changeTZ('US/Pacific')}>미국으로 바꾸기</button>
    </>
  )
}

export default Clock

예제6. props에서 변경할 timezone도 함께 받아 표시하기

import React, {useState} from 'react'
import moment from 'moment-timezone'

function Clock(props) {
  const {timezone, changeTZBtn} = props
  const [time, setTime] = useState(moment().tz(timezone).format('YYYY-MM-DD HH:mm:ss'))

  const changeTZ = (TZ) => {
    setTime(moment().tz(TZ).format('YYYY-MM-DD HH:mm:ss'))
  }
  return (
    <>
    <div>{time}</div>
    <button onClick={() => changeTZ(changeTZBtn)}>{changeTZBtn}바꾸기</button>
    </>
  )
}

export default Clock

constant폴더

constant폴더

  • 컴포넌트 안에서 선언하는 함수가 아니라 만들어놓은 데이터를 저장해놓고 가져와서 사용하고 싶을 때 관행적으로 사용하는 폴더입니다.
  • 우리는 현재 서버를 이용할 수 없기 때문에 이 constant 폴더 내부에 data.js를 만들어 공부해보도록 하겠습니다.

게시판 만들기

data.js

export const data = [
  {'id': 1, 'title': '제목1', 'content': '내용1'},
  {'id': 2, 'title': '제목2', 'content': '내용2'},
  {'id': 3, 'title': '제목3', 'content': '내용3'},
]

App.js

import React from 'react'
import {data} from '../components/data'

function Board() {
  return (
    <div>Board</div>
  )
}

export default Board

Board.js

import React from 'react'
import {data} from '../constant/data'

function Board() {
  return (
    <>
    {data.map((element) => {
      return (
        <>
          <h1>{element.title}</h1>
          <p>{element.content}</p>
        </>
      )
    })}
    </>
  )
}

export default Board

만약 category를 props로 받아 카테고리별로 표현을 하고 싶은 경우에는 아래와 같이 사용

data.js

export const data = [
  {'id': 1, 'title': '제목1', 'content': '내용1', 'category':'영화'},
  {'id': 2, 'title': '제목2', 'content': '내용2', 'category':'드라마'},
  {'id': 3, 'title': '제목3', 'content': '내용3', 'category':'예능'},
]

Board.js

import React, {useState} from 'react'
import {data} from '../constant/data'

function Board() {
  const [articles, setArticles] = useState(data.filter(element => (element.category==='영화')))

  return (
    <>
    {articles.map((element) => {
      return (
        <>
          <h1>{element.title}</h1>
          <p>{element.content}</p>
        </>
      )
    })}
    </>
  )
}

export default Board
  • 위 코드의 경우 category별로 데이터를 받아 필터링해서 사용을 할 수 있습니다. filter 내부에서의 return은 이제 리액트를 시작한다는 스타트 신호로 볼 수 있습니다

유사하지만 다른 풀이

0개의 댓글