[STUDY] 240408 | 리액트(React) | useState, 구조 분해 할당

Nimgnos·2024년 4월 16일
0

👾 STUDY

목록 보기
39/40
post-thumbnail

💻 React는 SPA(Single Page Apllication)

  • 단일 페이지 애플리케이션
  • 서버에서 필요한 데이터만 비동기로 받아와서 동적으로 현재 화면에 다시 렌더링 하는 방식
  • 다수의 페이지를 표시하는 데 있어서 과거 전통적인 방식으로 페이지 전환을 수행하지 않고, 마치 하나의 페이지인 것처럼 처리하는 기술
  • 주요 장점은 페이지 전환 시 서버에서 전체 화면을 새로 내려받지 않기 때문에, 뛰어난 반응성과 빠른 페이지 로딩을 가능케 함.
  • ⭐⭐⭐ useState ⭐⭐⭐

    : 값이 변하면 화면에 바로 적용되어 나타남

💻 리액트 개발 세팅

  • node.js 다운 + 설치
  • npm 문법 제공 : 필요한 라이브러리를 쉽게 설치할 수 있는 명령어
  • 리액트 프로젝트 생성을 위한 최초에 딱 한번만 실행하는 명령어
    npm install -g create-react-app : create-react-app 이라는 명령어 설치
  • 리액트 프로젝트 생성
  • 프로젝트가 될 폴더를 생성(🌟소문자로 생성)
  • vscode로 생성한 폴더 열기
  • vscode의 터미널에서 리액트 앱 프로젝트 생성 명령어 실행
    npx create-react-app . : 현재 폴더에 프로젝트 생성
  • 프로젝트 실행 > 터미널에서 npm start 명령어 실행
  • 프로젝트 종료 > 터미널에서 ctrl+c > Y
  • 자동저장 반응 속도 조절 (파일 > 자동저장 체크) (설정 > auto save > delay 300)
  • 화면 그림이 그려지는 곳 : App.js

📌 컴포넌트(Component)

  • 리액트로 만들어진 앱을 이루는 최소한의 단위
  • 재사용이 가능한 각각의 독립된 모듈 (재사용 가능한 UI 코드 조각)
    UI를 재사용 가능한 개별적인 여러 조각으로 나누고, 각 조각을 개별적으로 나누어 코딩
  • 데이터(props)를 입력받아 View(state) 상태에 따라 DOM Node를 출력하는 함수
  • “props”라는 임의의 입력을 받은 후, 화면에 어떻게 표시되는지 기술하는 React 엘리먼트를 반환

💡컴포넌트의 장점

  • 기존의 웹 프레임워크는 MVC방식으로 분리/관리하여 각 요소의 의존성이 높고 재활용이 어렵다는 단점 존재
    ➡️ 반면 컴포넌트는 MVC의 뷰를 독립적으로 구성하여 재사용을 할 수 있고, 이를 통해 새로운 컴포넌트를 쉽게 만들 수 있음.

💡유의사항

  • 컴포넌트 이름은 항상 대문자로 시작
    리액트는 소문자로 시작하는 컴포넌트를 DOM 태그로 취급하기 때문 !!
  • 컴포넌트는 파일 하나당 하나 생성하는 것을 권장

📌 구조 분해 할당 (Destructuring assignment)

  • 구조 분해 할당 구문은 배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 JavaScript 표현식
  • 배열 혹은 객체에서 각각 값(value)이나 프로퍼티(property) 를 분해하여 손쉽게 별도의 변수에 담을 수 있도록 해 줌.
  • (예) 함수나 객체에 배열을 전달해야 하는 경우, 객체나 배열에 저장된 데이터 전체가 아닌 일부만 필요한 경우 등 ... ➡️ 객체나 배열을 변수로 '분해’할 수 있게 해주는 구조 분해 할당을 사용할 수 있음.

📌 useState

  • state
    컴포넌트의 상태. 시간이 지남에 따라 변경될 수 있는 값
  • useState
    • 상태를 추가, 저장, 관리할 수 있게 해주는 hook.
    • 컴포넌트의 상태를 간편하게 생성하고 업데이트 해주는 도구를 제공
  • state 생성과 동시에 가져야할 초기값을 useState 함수에 인자로 넣어주면 state와 setState를 두가지 요소를 배열 형태로 리턴해 줌.
    const [state(상태 함수), setState(상태 변경 함수)] = useState(초기값);
    • 컴포넌트의 현재 상태 값은 state 라는 변수에 들어있고 state를 변경하고 싶으면 setState 함수를 이용해서 변경할 수 있다.
    • 여기서 state와 setState의 이름은 마음대로 지정할 수 있음.
    • setState를 이용해서 state를 변경하면 해당 컴포넌트는 화면에 다시 렌더링 됨.
  • 첫번째 데이터 [state(상태 함수), ] : useState의 소괄호 안의 데이터가 저장되는 변수
  • 두번째 데이터 [, setState(상태 변경 함수)] : 첫번째 데이터의 값을 변화시킬 함수

🤓 예제


App.js

  • 10이라 출력되는 화면의 숫자를 버튼 클릭 시 20으로 변경
  • 객체 생성, 다른 컴포넌트에 데이터 전달
import logo from './logo.svg';
import './App.css';
import Header from './components/Header';
import Body from './components/Body';
import Footer from './components/Footer';
import { useState } from 'react';

//props
function App() {
  //데이터를 Header 컴포넌트에 전달
  const num1 = 10;
  const myName = 'hong';
  const student = {
    'stuName' : '자바',
    'age' : 30,
    'score' : 80
  }

  //구조분해할당
  const arr = [1, 2, 3];
  const arr_0 = arr[0];
  const arr_1 = arr[1];
  const arr_2 = arr[2];

  //배열의 구조분해할당
  const [a, b, c] = arr;
  console.log(`a = ${a}`);
  const [a1, b1] = arr; //a1=1, b1=2
  const[a2, b2, c2, d2] = arr; //d2=undifined

  //객체의 구조분해할당
  //객체는 {}로 포현함
  const {stuName, age, score} = student;
  console.log(`stuName = ${stuName}`);
  const {age:abc} = student;
  console.log(abc);

  //10 -> 버튼 클릭 시 20으로 변경
  //(변화없음)
  let test_num = 10;

  function changeNum(){
    test_num = 20;
  }

  //10 -> 버튼 클릭 시 20으로 변경
  //★ useState 사용 ★
  //useState로 만든 변수의 값이 바뀌면 해당 변수를 선언한 컴포넌트가 재랜더링(소스코드를 다시 읽음)함.
  //첫번째 데이터 [testNum, ] : useState의 소괄호 안의 데이터가 저장되는 변수
  //두번째 데이터 [, setTestNum] : 첫번째 데이터의 값을 변화시킬 함수
  let [testNum, setTestNum] = useState(10);
  function chanegeTestNum(){
    setTestNum(20);
  }

  return (
    <div className="App">
      <div>{test_num} / {testNum}</div>
      <div>
        <button type='button' onClick={changeNum}>클릭!</button>
        <button type='button' onClick={chanegeTestNum}>React 클릭!</button>
      </div>
      <Header num1={num1} myName={myName} />
      <Body stuInfo={student} />
      <Footer/>
    </div>
  );
}

//연습용 컴포넌트
function TestComponent(){
  return(
    <div>연습용 컴포넌트</div>
  )
}

export default App;

Header.js

  • App.js에서 넘어오는 객체의 데이터 받기
  • 리턴문에서 최상위 태그는 1개여야함
  • 상위 컴포넌트에서 하위 컴포넌트로만 데이터가 전달이 됨.
  • props(properties) : 빈 객체를 받을 수 잇는 빈 통
  • onChange={(e) => {}}
    • e : 이벤트의 모든 정보가 담긴 객체
  • console.log(e.target) : 이벤트가 어디서 발생하는거냐?
  • console.log(e.target.name) : 이벤트가 걸린 태그의 네임 속성을 가져오겠다.
import { useState } from "react";
//App.js에서 넘어오는 데이터를 props로 받음
//props(properties) : 빈 객체를 받을 수 잇는 빈 통

//function Header({num1, myNam}){
    // -> {props.} 안해도 됨
function Header(props){
    console.log(props)
    //const {num1, myName} = props;
    // -> {props.} 안해도 됨

    //input 태그에 입력한 데이터를 저장할 변수
    let [addr, setAddr] = useState('');

    //onChange={(e) => {}}
    //e : 이벤트의 모든 정보가 담긴 객체
    //console.log(e.target) : 이벤트가 어디서 발생하는거냐 => <input type="text" name="addr">
    //console.log(e.target.name) : 이벤트가 걸린 태그의 네임 속성을 가져오겠다. => addr

    return(
        <>
            <div>
                <h1>Header!!!!</h1>
            </div>
            <div>
                App에서 넘어오는 객체 num1 데이터는 {props.num1}
            </div>
            <div>
                App에서 넘어오는 객체 myname 데이터는 {props.myName}
                <input type="text" name="addr" onChange={(e) => {
                    //console.log(e.target.value);
                    setAddr(e.target.value);
                }}/>
            </div>
        </>
    )
}
//헤더를 내보내겠다.
export default Header;

Body.js

  • App.js에서 넘어오는 객체의 데이터 받기
function Body(props){
    const num1 = 10;
    const num2 = 20;
    //객체 생성
    const person = {
        'name' : 'hong',
        'age' : 20
    }
    return(
        <>
            <div>
                <h2>Body</h2>
            </div>
            <div>
                {num1} / {num2} / {num1 + num2}
            </div>
            <div>
                객체 person의 이름은 {person.name}, 나이는 {person['age']}
            </div>
            <div>
                App에서 넘어오는 객체 stuInfo 데이터는 
                이름 : {props.stuInfo.stuName} / 
                나이 : {props.stuInfo.age} / 
                점수 : {props.stuInfo.score}
            </div>
        </>
    )
}
//바디(컴포넌트명)를 내보내겠다.
export default Body;

Footer.js

  • useState 사용. 제목 변경 버튼을 클릭하면 기존 제목에서 변경
  • 하위 컴포넌트 실행 시 상위 컴포넌트 실행되지 않음 !!!!!!!!!!!!
  • if문, for문 못씀 ➡️ 삼항연산자 사용
  • {중괄호} 내에서 연산, 로직 등 처리
import { useState } from "react";
function Footer(){
    console.log('Footer 랜더링');
    const num = 5;

    //★ useState 사용 ★
    const [title, setTitle] = useState('기존 제목');
    function chanegeTitle(){
        setTitle('변경된 제목');
    }

    //onClick={chanegeTitle} 실행 후 콘솔 확인 시,
    //console.log('Footer 랜더링');만 출력되는 것을 알 수 있음
    //-> 하위 컴포넌트 실행 시 상위 컴포넌트 실행되지 않음 !!!!!!!!!!!!

    //if문, for문 못씀 - 삼항연산자 사용
    //{중괄호} 내에서 연산, 로직 등 처리
    return(
        <>
            <div>
                <h3>Footer</h3>
            </div>
            <div>
                {num & 2 == 0 ? '짝수' : '홀수'}입니다.
            </div>
            <div>
                {title}
            </div>
            <div>
                <button type="button" onClick={chanegeTitle}>제목 변경 1</button>
                <button type="button" onClick={() => {setTitle('변경된 제목 2')}}>제목 변경 2</button>
            </div>
        </>
    )
}
//푸터(컴포넌트명)를 내보내겠다.
export default Footer;


🔍 참조

profile
먹고 기도하고 코딩하라

0개의 댓글