리엑트 - Hooks(스테이트 변수)

songmin jeon·2024년 4월 23일
0

  • 불러오기 방법

    import React, { useState } from "react";

useState

스테이트 변수 와 일반 변수

  • 리엑트는 변경되는 값 화면과 변경되는 값을 유동적으로 보여지는화면이 분리되어 있음.

  • 일반 변수(값변화가 실시간 안보임)

  • 스테이트 변수(변경된 값이 실시간으로 보임)


스테이트 변수 사용해보기

  • { useState } 기능을 import 해주기

const [number, setNumber] = useState(0);

number : 실제 값을 가지고 있는 변수(state값)
setNumber : state값을 바꿀 수 있는 기능


import React, { useState } from "react";

const Ex01 = () => {
  // 특별한 변수를 만드는 방법
  // -> 값이 변경될때 마다 화면에 적용되어질 변수를 만드는 방법
  // number : 실제 값을 가지고 있는 변수(state값)
  // setNumber : state값을 바꿀 수 있는 기능
  const [number, setNumber] = useState(0);

  let num = 0;

  function plus() {
    num++;
    console.log(num);

    setNumber(number + 1);
  }

  return (
    <div>
      <div>{number}</div>
      <button onClick={plus}>PLUS</button>
    </div>
  );
};

export default Ex01;

es6 문법의 문제

  • 해당 코드에 원클릭 변수 호출시 ( ) => 가 없으면 무한 반복으로 함수가 호출 된다.

  • ( ) => 는 에로펑션 이라 불린다.

  • 주의 ! state 값이 바뀌어지면 -> 컴포넌트가 재랜더링(재실행) 된다!

import React, { useState } from "react";

let num1 = Number(prompt("첫번째 숫자 입력"));
let num2 = Number(prompt("두번째 숫자 입력"));

const Ex02 = () => {
  // result : state 값을 가지는 변수
  // setResult : state 변수를 바꿀 수 있는 함수
  // 주의 ! state 값이 바뀌어지면 -> 컴포넌트가 재랜더링(재실행) 된다!
  const [number, setNumber] = useState(0);

  function result(string) {
    if (string === "+") {
      setNumber(num1 + num2);
    } else if (string === "-") {
      setNumber(num1 - num2);
    } else if (string === "*") {
      setNumber(num1 * num2);
    } else if (string === "/") {
      setNumber(num1 / num2);
    }
  }

  return (
    <div>
      <button onClick={() => result("+")}>+</button>
      <button onClick={() => result("-")}>-</button>
      <button onClick={() => result("*")}>*</button>
      <button onClick={() => result("/")}>/</button>
      <p>{number}</p>
    </div>
  );
};

export default Ex02;

useRef

  • React에서 태그를 가져올때 document를 통한 태그 선택은 절대 권장하지 않음

사용방법

  • useRef : 태그를 참조할 수 있는 React Hook

    import React, { useRef } from "react";


입력하는 값에 따라 화면 출력 해보기

import React, { useRef, useState } from "react";
// React Hook 사용법 1. 사용하고자 하는 hook을 import 해줘야 한다.

const Ex03 = () => {
  // React Hook 사용법 2. 기능을 컴포넌트 안에 있는 변수에 담아주기
  const input = useRef();

  // input 태그에 적은 값을 가져와서 반양시킬 state
  const [inputText, setInputText] = useState("");

  return (
    <div>
      <h1>Input태그 다루기</h1>

      {/* 
        <input ref={input}></input>
        -> input 변수를 통해서 input 태그에 매칭 시켜주겠다.
    */}
      <input
        ref={input}
        onChange={() => setInputText(input.current.value)}
      ></input>
      {/* 
        input.current == document.querySelector('input')
      */}
      <h1>{inputText}</h1>
    </div>
  );
};

export default Ex03;
  • 입력한데로 값이 들어 간다.


태그를 참조하는 기능

  • input 태그에 값을 참조한다.

<input ref={num1} ./>

  • num1 이라는 변수에 input 태그가(값 속성 모두) 들어간다.

const num1 = useRef();

  • nm1 변수에 input에 담긴 값을 정수형으로 형변환 한다.

let nm1 = parseInt(num1.current.value);


리액트 부트 스크랩

  • 주소창에 리액트 부트 스크랩 검색 > get stated

  • 해당 내용 복사 > 터미널 종료 이후 입력 > 설치됨!

npm install react-bootstrap bootstrap

  • 설치완료됬는지 확인 방법

  • 리액트 부트 스크랩을 사용할때는 css 를 import 해줘야함

  • 그외 필요한 샘플은 해당 위치에서 맞춰 찾아 볼 수 있다.

  • 예로 버튼 종류


실습 주사위 굴리기

  • 해당 구조로 만들 예정

  • 폴더에 해당 파일 만들어주기

  • index.js에서 연결하여 호출 > npm start

  • DiceApp.jsx

import "bootstrap/dist/css/bootstrap.min.css";
import React, { useState } from "react";
import ButtonArea from "./ButtonArea";
import BoardArea from "./BoardArea";
import "./dice.css";

const DiceApp = () => {
  // 나와 컴퓨터에 대한 정보를 가진 state 생성(값 형태 : 객체)
  const [user, setUser] = useState({
    name: "나",
    diceNum: "1",
    score: "0",
    imgPath: "./img/dice1.png",
  });

  const [com, setCom] = useState({
    name: "컴퓨터",
    diceNum: "1",
    score: "0",
    imgPath: "./img/dice1.png",
  });

  const throwDice = () => {
    console.log("주사위 던지기!");

    // 랜덤 숫자 생성 -> 숫자 비교, 이미지 값 적용
    // Math.random() : 실수를 생성하는 함수
    // Math.floor() : 소수점을 버림
    let userDiceNum = Math.floor(Math.random() * 6) + 1;
    let comDiceNum = Math.floor(Math.random() * 6) + 1;
    let userScore = parseInt(user.score);
    let comScore = parseInt(com.score);

    // 두 주사위 눈 비교
    // 1) 동일한 숫자일 때 -> 무승부 출력 카운트 필요없음
    // 2) 나의 숫자가 클 때 -> 나의 카운트 +1
    // 3) 컴퓨터의 숫자가 클 때 -> 컴퓨터의 카운트 +1

    if (userDiceNum > comDiceNum) {
      userScore += 1;
    } else if (userDiceNum < comDiceNum) {
      comScore += 1;
    }

    // 결과 값을 state에 반영 -> 웹 페이지의 정보를 업데이트
    // { ...user } -> {name:'', diceNum:1. score:0, imPath:''} 분할 -> spread 연산자
    setUser({
      ...user,
      diceNum: userScore,
      score: userScore,
      imgPath: `./img/dice${userDiceNum}.png`,
    });

    setCom({
      ...com,
      diceNum: comScore,
      score: comScore,
      imgPath: `./img/dice${comDiceNum}.png`,
    });
  };

  // 초기화 기능 구현하기
  // 함수명 : initDice
  function initDice() {
    setUser({
      ...user,
      diceNum: 0,
      score: 0,
      imgPath: `./img/dice1.png`,
    });

    setCom({
      ...com,
      diceNum: 0,
      score: 0,
      imgPath: `./img/dice1.png`,
    });
  }

  return (
    <div className="container">
      <h1>주사위 게임</h1>
      <ButtonArea throwDice={throwDice} initDice={initDice} />
      <BoardArea user={user} com={com} />
    </div>
  );
};

export default DiceApp;
  • ButtonArea.jsx
import React from "react";
import Button from "react-bootstrap/Button";

const ButtonArea = ({ throwDice, initDice }) => {
  return (
    <div className="button-area">
      <Button variant="warning" onClick={() => throwDice()}>
        던지기
      </Button>
      <Button variant="danger" onClick={() => initDice()}>
        초기화
      </Button>
    </div>
  );
};

export default ButtonArea;
  • BoardArea.jsx
import React from "react";
import Board from "./Board";

const BoardArea = ({ user, com }) => {
  return (
    <div className="board-area">
      <Board user={user} />
      <Board user={com} />
    </div>
  );
};

export default BoardArea;
  • Board.jsx
import React from "react";

const Board = ({ user }) => {
  console.log(user);
  return (
    <div className="board">
      <h4>{user.name}</h4>
      <img src={user.imgPath} alt="이미지 없음." />
      <div className="score-area">
        <h4>현재 점수는?</h4>
        <h4>{user.score}</h4>
      </div>
    </div>
  );
};

export default Board;
  • dice.css
.container {
  display: flex;
  justify-content: center;
  flex-direction: column;
  text-align: center;
  height: 100vh;
}

.button-area > button {
  margin-left: 10px;
}

.board-area {
  display: flex;
  justify-content: center;
}

.board-area > div {
  margin-left: 10px;
  margin-top: 20px;
}

.score-area {
  margin-top: 20px;
}

profile
제가 한 번 해보겠습니다.

0개의 댓글