connecting dots

Beginner 2회차(7/24) | JS 기본, 프로젝트 구조 알아보기, 리액트 훅/useState()/반응성/return, 구조 분해 할당 본문

Live Class/Beginner

Beginner 2회차(7/24) | JS 기본, 프로젝트 구조 알아보기, 리액트 훅/useState()/반응성/return, 구조 분해 할당

dearsuhyun 2024. 7. 24. 16:52

*  

              줄래 ?

       (요청, request)

브라우저 <--> https://www.heropy.com

                줄게

       (응답, response)

 

가장 먼저 ! html 가져옴 (화면의 구조를 그림. index.html)

http = 프로토콜 (통신 규약) + s --> 보안을 위해서 !

 

로컬 서버(개발 서버) 실제 서버가 아님. 개발할 때만 씀

vs

배포 (다른사람이 접근할 수 있는 서버로)

 

*

for (let i = 0; i < 10; i++) {}
for (let i = 0; i < 10; i += 1) {}

++ 보다 +=를 추천 (더 명확함)

 

*

<script defer src="./index.js"></script>

defer를 사용한다 = html 우선 먼저 다 읽고 나서 js 실행해줘 ! (먼저 불러오지만 html 다 읽을 때 까지 대기)

 

 

JS 코드 뜯어보기

const usersEl = document.querySelector(".realtime-users");
// 요소.addEventListener(이벤트이름, 함수(이벤트핸들러))
// 해당 요소에 이벤트가 발생하는지 듣고 있다가, 이벤트가 발생하면 함수를 실행해주세요

const countEl = document.querySelector(".user-count");
// countEl = <span class="user-count">31명</span>

usersEl.addEventListener("click", () => {
  const newCount = Number(countEl.textContent) + 1; 
  // get 값을 읽기 (값을 읽을 때 쓰는 함수 = getter)
  
  countEl.textContent = newCount; 
  // set 값을 쓰기 (값을 쓸 때 쓰는 함수 = setter)
  
  users.forEach();
});

// textContent = 31, 문자 / 숫자로 만들기 위해서는 Number() 사용
// typeof --> string

// null = 값이 없어요 vs undefined = 정의 안됨

// Number('31') + 1 = 32
// 이름 복수 --> 배열데이터일 가능성 높음. 이름을 잘 만들어야 함 (협업)
const users = [
  { name: "Heropy", age: 85 },
  { name: "Neo", age: 23 },
  { name: "Lewis", age: 30 },
];

const realtimeUserCountEl = document.querySelector('.realtime-user-count')
const countEl = document.querySelector('.count')
const userListEl = document.querySelector('ul.users')
realtimeUserCountEl.addEventListener('click', () => {
  const newCount = Number(countEl.textContent) + 1
  countEl.textContent = newCount
  renderUsers()
})

renderUsers()
// 서버에서 사용자 목록을 다시 가져온 상태인 경우

function renderUsers() {
  const liEls = users.map(user => {
    const liEl = document.createElement('li')
    liEl.textContent = user.name
    return liEl
    })
    usersEl.append(...liEls)
}

 

createElement, append, (...)

  const liEls = users.map(user => {
    const liEl = document.createElement('li')
    liEl.textContent = user.name
    // <li>heropy</li>
    return liEl
    })
    // [<li>heropy</li>, <li>Neo</li>, <l>Lewis</li>]
    // map 메소드를 사용하면 배열 데이터가 반환됨
    usersEl.append(...liEls)
      // 전개연산자(spread) 배열 데이터를 감싸고 있는 대괄호를 날리는 역할.
      // append 뒤에 넣는다
      // <li>heropy</li>, <li>Neo</li>, <li>Lewis</li>

 

forEach()

// 배열 데이터는 순서가 있고 객체 데이터는 순서가 없다
const numbers = [4,5,6,7,8]

// for 반복문
for (let abc=0, abc < numbers.length, abc += 1) {
  console.log(numbers[abc])
}

// forEach 메소드
// numbers.forEach(콜백함수)
// 매개변수(paramater), 인수(argument, 매개변수로 전달되는 값)
// numbers.forEach(function (number -> 매개변수(paramater), 이미 여기서 선언됨)
// number = 현재 요소의 값, index = 현재 요소의 인덱스, array = 원본 배열

  numbers.forEach = function (number, index, array) {
  	console.log('---')
    console.log(number)
    console.log(index)
    console.log(array)
  }
  
  // 출력 결과
---
4
0
[ 4, 5, 6, 7, 8 ]
---
5
1
[ 4, 5, 6, 7, 8 ]
---
6
2
[ 4, 5, 6, 7, 8 ]
---
7
3
[ 4, 5, 6, 7, 8 ]
---
8
4
[ 4, 5, 6, 7, 8 ]

  const double = numbers.map = function (number) {
    console.log(number) // 4, 5, 6, 7, 8
    return number * 2 // [8, 10, 12, 14, 16]
  }

  double = []

 

vite 프로젝트

Vite js

main.tsx

진입점(엔트리 포인트)

여러개 설정 가능하지만 기본적으로는 하나 ! (webpack에서 공부해야 하긴 함)

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'

 

모두 연결이 되어있기 때문에 여기서 시작하면 됨

cf. 모두 연결이 되어있어야 하긴 함

 

App.tsx

최상위 컴포넌트(root component): 가장 최상단에 위치한 컴포넌트

 

package.json 설명

{
  "name": "devcamp", // 내 프로젝트의 이름. 내 프로젝트도 하나의 패키지임. 내가 설치한 패키지랑 이름 중복되면 안됨.
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.3.1", // 내 패키지 이름으로는 사용할 수 없음
    "react-dom": "^18.3.1" // 내 패키지 이름으로는 사용할 수 없음
  },
  "devDependencies": {
    "@types/react": "^18.3.3",
    "@types/react-dom": "^18.3.0",
    "@typescript-eslint/eslint-plugin": "^7.15.0",
    "@typescript-eslint/parser": "^7.15.0",
    "@vitejs/plugin-react-swc": "^3.5.0",
    "eslint": "^8.57.0",
    "eslint-plugin-react-hooks": "^4.6.2",
    "eslint-plugin-react-refresh": "^0.4.7",
    "typescript": "^5.2.2",
    "vite": "^5.3.4"
  }
}

 

semantic versioning(SemVer)

의미론적 버전 매기는 방법

1.0.0

메이저 버전.마이너 버전.패치 버전

"build": "tsc -b && vite build"
// 배포할 때의 결과물을 만드는 것

 

리액트에서의 return

 

리액트에서는 단일요소가 return 되어야 함

 

 

==> 단일요소 아니라서 오류 발생

 

 

flagment로 단일 요소 만들어주기 (<div> 대신 !)

flagment는 요소가 아님. 안쪽에 있는 내용만 출력됨

 

반응성(Reactivity)

 

console에서는 찍히는데 화면은 바뀌지 않는 상황 (데이터는 바뀌는데 화면은 안 바뀜)

 

 

반응성 !

데이터가 변경할 경우 화면도 반응하여 같이 바뀐다 !

이 때 사용되는 데이터 = 반응형 데이터

useState() Hook !을 사용하여 보통 만든다

모던 프레임워크(React, Vue, Angular) 정체성

import { useState } from 'react'

// 반응형 데이터 선언
const [데이터이름, 데이터변경함수] = useState(기본값)

// 반응형 데이터 변경
데이터변경함수(변경할값)

 

이제 화면도 잘 변경된다 !

 

이벤트 핸들러

사용자가 웹 페이지와 상호작용할 때 발생하는 사건(이벤트)을 처리하는 방법

 

이벤트 핸들링의 기본 개념

 

1. 이벤트(Event):

사용자가 웹 페이지와 상호작용할 때 발생하는 사건입니다.

예: 클릭 이벤트, 키보드 입력 이벤트, 마우스 이동 이벤트 등.

2. 이벤트 핸들러(Event Handler):

특정 이벤트가 발생했을 때 실행되는 함수입니다.

이벤트 핸들러는 이벤트가 발생할 때마다 호출되어 정의된 동작을 수행합니다.

3. 이벤트 리스너(Event Listener):

특정 이벤트를 감지하고, 이벤트가 발생하면 지정된 이벤트 핸들러를 실행하는 역할을 합니다.

이벤트 리스너는 보통 addEventListener 메서드를 사용하여 등록합니다.

 

예시: onClick, onChange, onMouseOver

<button onClick="alert('버튼이 클릭되었습니다')">Click Me</button>
// 버튼이 클릭되면 경고창 나타남

<input type="text" onChange="console.log(this.value)" placeholder="Type something here">
// 입력 필드의 내용이 변경되면 콘솔에 새로운 값이 출력됨

<div class="hover-box" onMouseOver="this.style.backgroundColor='lightgreen'" onMouseOut="this.style.backgroundColor='lightblue'">
    Hover over me!
  </div>
// 사용자가 특정 영역에 마우스를 올리면 배경색이 변경됨

 

왜 [ ]를 사용할까 ? 구조 분해 할당 !

 

화면에 표시하기

 

1. useState 훅 가져오기

useState는 React 훅 중 하나로, 함수형 컴포넌트에서 상태를 관리할 수 있게 해줍니다.

import { useState } from "react";

 

2. App 컴포넌트 정의

useState를 사용하여 두 개의 상태 변수를 정의합니다.

users: 사용자 목록을 저장하는 상태 변수입니다.

setUsers: 사용자 목록을 업데이트하는 함수입니다.

count: 카운터 값을 저장하는 상태 변수입니다.

setCount: 카운터 값을 업데이트하는 함수입니다.

초기값은 31로 설정되어 있습니다.

export default function App() {
  // 초기 사용자 목록 상태 설정
  const [users, setUsers] = useState([
    { name: "Neo", age: 51 },
    { name: "Lewis", age: 22 },
    { name: "Evan", age: 18 },
  ]);

  // 초기 카운터 상태 설정
  const [count, setCount] = useState(31); // 31 = 초기값 (default value, 처음에 뜨는 값)

 

3. increase 함수 정의

increase 함수는 setCount를 사용하여 count 값을 1 증가시킵니다.

  function increase() {
    setCount(count + 1);
  }

 

4. JSX 반환

JSX는 React 컴포넌트의 UI를 정의하는 문법입니다.

  return (
    <>
      <div>{count}명</div>
      <button onClick={increase}>증가+</button>
      <ul>
        {users.map((user) => (
          <li key={user.name}>{user.name}</li>
        ))}
      </ul>
    </>
  );
}

<div>{count}명</div>: 현재 count 값을 보여줍니다.

<button onClick={increase}>증가+</button>: 클릭 시 increase 함수를 호출하여 count 값을 증가시킵니다.

<ul>: 사용자 목록을 순회하여 각 사용자의 이름을 <li> 요소로 출력합니다.

 

초기 화면과 버튼 누르면 명 수가 증가하는 화면

학습해야 할 것
- array method 강의에서 짚어 주신 부분 학습 (탁 치면 툭 튀어나올 정도로 학습되어야 함. 외우세요)
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/at
- 구글 크롬 원격 제어 설치
https://www.heropy.dev/p/XLGqke
- 자바스크립트 강의 등을 빠르게 들어서 복습하기 (블로그 등 활용)
반응형