본문 바로가기
학원수업/3월

03/10 국비학원 개발자 71회차 수업-React, 싱글페이지 어플리케이션

by 코딩마스터^^ 2023. 3. 10.

불필요한 div를 가질 필요가 없다.

프레그먼트

<>

</>

넣어준다.

 

 React는 js기본 문법을 아는것이 가장 중요하다.

props가 바뀌었을때 상태값이 바뀐다.

props가 바뀌었을때도 리렌더링이 일어난다.

 

 

리렌더링 경우

1. state가 변경되었을때 리렌더링이 일어난다.

2. Props가 변경되었을때

3. 부모 컴포넌트가 변경 되었을때

캡쳐링만 된다. 버블링은 안된다.

 

React에서 리렌더링은

컴포넌트의 상태(state)나 속성(props)이 변경될 때 해당 컴포넌트가 다시 렌더링되는 것을 의미합니다.

React는 Virtual DOM을 사용하여 컴포넌트의 렌더링을 최적화합니다.

Virtual DOM은 실제 DOM의 가벼운 복사본으로, 컴포넌트의 상태나 속성이 변경될 때마다 새로운 Virtual DOM을 생성하고 이전 Virtual DOM과 비교합니다.

이전 Virtual DOM과 새로운 Virtual DOM이 다른 경우에만 React는 실제 DOM을 업데이트하여 새로운 뷰를 렌더링합니다.

리렌더링은 어플리케이션 성능에 영향을 미칠 수 있기 때문에, React는 불필요한 리렌더링을 최소화하기 위해 다양한 최적화 방법을 제공합니다.

예를 들어, shouldComponentUpdate() 메서드를 사용하여 컴포넌트의 업데이트를 컨트롤하거나, PureComponent나 React.memo()를 사용하여 불필요한 리렌더링을 방지할 수 있습니다.

 

첫글자가 소문자이면 이벤트함수이다.

 

렌더함수는 return에서 호출된다.

컴포넌트가 불려졌을때 함수가 실행이 된다.

함수도 객체이다.

일급함수 

함수도 객체이다. 주소번지를 갖는다. 주소달라지면 리렌더링

 

 

운동 화면에서 운동별로 반복적으로 메뉴가 나오게 하고 싶다!!

import { Route, Routes } from 'react-router-dom';
import './App.css';
import LoginPage from './components/login/LoginPage';
import DeptPage from './components/page/DeptPage';
import EmpPage from './components/page/EmpPage';
import HackerNewsPage from './components/page/HackerNewsPage';
import HomePage from './components/page/HomePage';
import WorkoutPage from './components/page/WorkoutPage';
import YoutubePage from './components/page/YoutubePage';
import FireDeptPage from './components/page/FireDeptPage';
import { useState } from 'react';
//index.js에서 브라우저 라우터로 감싸진 App태그 속성값으로 넘어온 주소번지를 받는다.
const App=({authLogic})=> {
  const [items,setItems]=useState([
    {id:1,name:'벤치프레스',count:0},
    {id:2,name:'밀리터리프레스',count:0},
    {id:3,name:'오버헤드스쿼트',count:0},
  ]);
  //사용자 정의 컴포넌트에서 return다음에 오는 코드가 element의 집합이다.
  //Router이용하면 SPA(single page application)누릴 수 있다.
  return (
  <>
  <Routes>
    <Route path='/' exact={true} element={<LoginPage authLogic={authLogic}/>}/>
    <Route path='/home/:userId' exact={true} element={<HomePage authLogic={authLogic}/>}/>
    <Route path='/board' exact={true} element={<DeptPage authLogic={authLogic}/>}/>
    <Route path='/workout' exact={true} element={<WorkoutPage authLogic={authLogic} workouts={items}/>}/>
    <Route path='/hackernews' exact={true} element={<HackerNewsPage authLogic={authLogic}/>}/>
    <Route path='/youtube' exact={true} element={<YoutubePage authLogic={authLogic}/>}/>
    <Route path='/dept/:id' exact={true} element={<FireDeptPage authLogic={authLogic}/>}/>
    <Route path='/emp' exact={true} element={<EmpPage/>}/>
  </Routes>
  </>
  );
}
export default App;

 

import React, {useEffect} from 'react'
import { useNavigate, useParams } from 'react-router'
import Bottom from '../include/Bottom'
import Header from '../include/Header'
import Workouts from '../workout/Workouts'

const WorkoutPage = ({authLogic, workouts}) => {
	const navigate = useNavigate()
	let { userId } = useParams()
	console.log(userId)
	const onLogout = () => {
		console.log('workoutPage onLogout 호출')
		authLogic.logout()
	}

	useEffect(() => {
		authLogic.onAuthChange(user => {
			if(!user){
				navigate("/")
			}
		})
	})
  return (
  <>
    <Header onLogout={onLogout}/>
    <Workouts workouts={workouts}/>{/* 자손 컴포넌트 호출 */}
    <Bottom/>
  </>
  )
}

export default WorkoutPage

 

import React, { useState } from 'react'

const Workouts = ({workouts}) => {
  const [name, setName]=useState("default");
  const [count, setCount]=useState(0);
  const handleIncrement=()=>{

  }
  const handleDecrement=()=>{
    
  }
  const handleDelete=()=>{
    
  }
  return (
    <>
    <ul>
    
      {workouts.map((items,index)=>(/* 맵으로 꺼낸다... 요소를 하나씩 꺼낸다.for문이라고 생각하자! */
      <li>
        <h3>{items.name}</h3>
        <h3>{items.count}</h3>
       < button className="habit-button habit-increase" onClick={handleIncrement}>
          <i className="fas fa-plus-square"></i>
      </button>
      <button className="habit-button habit-decrease" onClick={handleDecrement}>
          <i className="fas fa-minus-square"></i>
      </button>
      <button className="habit-button habit-delete" onClick={handleDelete}>
          <i className="fas fa-trash"></i>
      </button>
      </li>
      ))}
    </ul>
    </>
  )
}

export default Workouts

 

값을 넘겨줄때 프롭으로 보낸다.

props로 파라미터 형식으로 값을 넣어준다.

꺼낼때 Map형식으로 하나하나 꺼내서 for문처럼 돌린다. 반복이 되개한다.

태그를 직접 쓰지말고 Workout에 한줄만 쓴걸 사용할수있다.

 

리액트에서 useState Hook 형식에서 seItems는 값을 넣어줄때 쓰는 함수인듯하다.

 

index.js 에서는 App 컴포넌트를 BrowserRouter 로 감싸준다.

왜냐하면 SPA로 처리하면서 화면 이동은 필요하기 때문에 router를 사용합니다.

BrowserRouter가 있어야 한 페이지안에서 이동이 된다.

싱글페이지 어플리케이션-한 페이지 안에서 이동이 일어난다. 화면이 한정되어있다. 아이패드 핸드폰 등등... 

최적화하고 싶다. 바뀐것만 새로 뿌려주고싶다. 안바뀐건 안뿌려주고 바뀐것만.

 

구글 로그인에 대한 처리를 담당하는 공통코드 authLogic클래스를 모든 컴포넌트에서 재사용해야하니까

 생성된 객체는 app컴포넌트에도 전달해야한다.

이때 props를 활용하여 부모 컴포넌트의 주소번지를 자손 컴포넌트에 넘길 수 있다.

 

BrowserRouter는

React.js의 컴포넌트 중 하나로, 싱글 페이지 애플리케이션에서 클라이언트 측 라우팅을 구현할 수 있게 해줍니다. BrowserRouter를 사용하면 애플리케이션의 여러 경로를 정의하고, 사용자가 링크를 클릭하면 새로운 요청 없이 해당 컴포넌트를 로드할 수 있습니다.

BrowserRouter는 HTML5 history API를 사용하여 애플리케이션의 탐색 히스토리를 관리합니다. 사용자의 위치를 추적하고 주소 표시 줄의 URL을 업데이트합니다. 이렇게하면 사용자가 브라우저의 뒤로 및 앞으로 버튼을 사용하여 애플리케이션의 히스토리를 탐색할 수 있습니다.

BrowserRouter를 사용하려면 애플리케이션을 감싸고 사용할 라우트를 정의해야합니다. 각 라우트는 컴포넌트로 정의되며 경로를 지정할 수도 있습니다. 예를 들어 홈 페이지에 대한 경로를 정의하려면 다음과 같이 정의 할 수 있습니다:

 

태그들을 재사용하고싶다. 바뀐것만 랜더링하고싶기때문이다.

li에 key를 사용했다.

key는 유니크해야되고 타입이 바뀐것을 키를 기준으로 판단한다.

비교알고리즘이 작동한다.

 

리액트 서버가 기동되면 index.html을 읽는다. -> 노드.js의 영역X 브라우저의 영역
그 안에 root가 있다. 그걸 불러줌. -> index.html안에는 다른게 없고 root만 있으면 됨.
바닐라 때는 innerHtml로 처리했었고 js때는 html함수(????)로 처리했었음. -> 삽입
그 안에 들어가는 건 html 태그들. 그 태그들을 재사용하고 싶다. 바뀐 것만 렌더링하고 싶음. 바뀌지 않은 건 읽어오고싶지X 퍼포먼스 향상을 위해.
그래서 태그 안에 key를 설정. 유니크해야함. 키를 기준으로 타입이 바뀌었는지 확인 ~ 비교 알고리즘.

 

 

React 흐름 살펴보기

 

1. yarn start

-yarn은 node package manager

얀을 설치한 정보가 package.json에 들어간다.

 

설치할때 2가지 사용가능

1)npm i -d XXX

2)yarn add XXX

 

그중에 나는 yarn을 사용해서 설치를하였다.

리액트, 리택트 돔, 리액트 라우터, 폰트어썸, 리액트 부트스트랩 등등 설치함

 

index.html을 찾는다.->div->id root->

 

끼워넣기의 목적은 싱글 페이지 어플리케이션(SPA)

 

Dom tree을 그려주는 역할을 브라우저가 그려준다.

돔 트리는 상속구조이다.

내려서만 props 를 전달할 수 있다.->캡쳐링(부모가 자식에게 전달)

 

spread연산자와 구조분해할당을 사용해서 props를 전달한다.

 

json의 차수가 점점 더 복잡해진다. List안에 map안에 vo...

그래서 구조분해 할당을 해야한다.

필요한 값을 상위 컴포넌트에서 자손에게 넘길때 스프레드 연산자를 사용한다.

 

바닐라 스크립트 index.js에서 인증객체를 생성한다.

authLogic.js--->바닐라 스크립트(순수하면 재사용성 좋다)

ㄴAuthLogic함수가 정의되어있다.

함수는 객체이다. 주소번지를 가진다.

dependency array

useEffect

useState

 

기억해줘=캐쉬등록(Memorization)

useMemo-값을기억-리턴이필요하다

useCallback-함수전체를 기억-리턴이필요없다

랜더링의 효율성. 퍼포먼스와 관계있다.

리액트는 리렌더링을 최소화하는것이 목표이다.

 

index.js에서 authLogic객체를 생성했다.

index.js에서 BrowserLouter로 묶어줬다.

AuthLogic 의 주소번지를 App에 담는다.

자바스크립트에서는 function도 객체이다. 주소번지가 바뀐다. 주소번지가 리렌더링의 기준값이다.

 

App이 실행이 될 때 App객체를 가지고 잇는 것은 App.jsx이다.(리액트)

태그와 자바스크립트를 섞어 쓰는것이다. Html, js섞어

자바에서 {} 는 클래스의 영역이다. 

자바스크립트에서는 {} 섞어쓰기이다.

App.jsx에서는 <Routes>가 온다.

화면의 갯수만큼 라우트가 복수로 온다.

라우트에는 URL이 온다.

라우트캐그는 element속성이 온다.

 element안에는 태그가 온다.

element에는 사용자 정의 컴포넌트가 온다.

페이지라고 쓰고 템플릿이라고한다...?

사용자의 컴포넌트로 페이지 설계함.

위 아래에 헤더/바텀을 붙여줬다.

 

props로 넘기는 객체는 items

items는 state Hook이다. state Hook이 바뀌면 relendering이 즉시 일어난다.

useStateHook에 하면 즉시 반영이된다. 동기화가 되어있다. 

함수도 초기화가된다. 그때마다 값이 0으로 돌아가면..? 망한다.

그래서 값을 기억하는 useMemo, useCallback을 사용한다. 유지가 된다.

 

예를 들어 페이지 이동후에 다시 돌아왔는데 값이없다? 그러면 안됨...

 

index.js(const authLogic=new AuthLogic())에서 객체 생성을 하였다.

 

생성된 객체(AuthLogic.class)는 App컴포넌트에도 전달(props)해야한다.

props에 여러가지를 담을 수 있다.

<App authLogic={authLogic} item={item} onLogout={onLogout}/>

 

이때 props를 활용하여 부모 컴포넌트의 주소번지를 자손 컴포넌트에 넘길 수 있다.

 

App.jsx

<Routes>

<Route path="" exact={true} element ={<HomePage authLogic={authLogic}/>}

</Routes>

 

WorkoutPage -> Workouts(map, key)키가 꼭 있어야한다. ->Workout

{

workouts.map((item, index)) =>(

   Workout workout(1row)={row} 

))}

 

데이터는 App에 있다.

workout에는 이벤트 핸들러있다.

props로 객체를 보낼때

통으로 (props)=>{} 이렇게 보내면 

밑에서 workout이랑 onincrement로 쪼개줘야한다=구조분해할당

구조분해 할때에는 value를 쓰는것이 아니라 속성명을 사용한다.

속성이 3개이다. props가 3개이다.

 

 

index.js-> App.jsx

->WorkoutPage.jsx->반복문-map(로우 주소번지, 인덱스, 배열객체자신)

 

반복문이 오는 자리에 key가 필요하다.

 

 

상태를 관리하는 훅이다. App.jsx에서 증가 이벤트 처리를 한다.

데이터 셋은 array이다. 어레이 안에 객체가 들어있다.

items는 배열 item은 row값

 

 

 

//props로 넘길때 파라미터를 따로 작성하지 않아도 넘어감-동일한 함수 선언 불가

댓글