요르딩딩

섹션6. React.js 입문 본문

[강의]/[한 입 크기로 잘라 먹는 리액트(React.js)]

섹션6. React.js 입문

요르딩딩 2025. 3. 28. 13:51
728x90
반응형

섹션5. React.js 개론

// 리액트앱 생성.
npm create vite@latest 

// package.json의 dependencies들 설치.
npm i 

// 실행
npm run dev

// eslint 확장 프로그램 설치
// 작성한 코드를 정적으로 검토하여 미리 오류로 띄워줌
.eslinttrc.cjs > "no-unused-vars" : "off", (미사용변수 오류처리 안되도록.)
.eslinttrc.cjs > "react[prop-types" : "off" (안전하게 사용할수 있도록 해주지만 실습시 불필요)

 

5.2) React 컴포넌트

// App.jsx
App Component : HTML 태그를 반환하는 함수 (함수 컴포넌트)

// 컴포넌트 생성 방법
// 첫글자는 대문자!!!
1. function Header(){} 
2. const Header = () => {}

// App(부모 컴포넌트) -> Header(자식 컴포넌트), Main, Footer
// App(루트 컴포넌트)

// 컴포넌트 가져오기/내보내기
import Header from "./components/Header";
export default Header;

 

 

5.3) JSX로 UI 표현하기

import "./Main.css";

// JSX 주의 사항
// 1. 중괄호 내부에는 자바스크립트 표현식만 넣을 수 있다
// 2. 숫자, 문자열, 배열 값만 렌더링 된다
// 3. 모든 태그는 닫혀있어야 한다
// 4. 최상위 태그는 반드시 하나여야만 한다. <></> 빈태그도 가능 -> 흩뿌려져있는것으로 간주
const Main = () => {
  const user = {
    name: "이정환",
    isLogin: true,
  };

  if (user.isLogin) {
    return <div className="logout">로그아웃</div>; // logout은 CSS파일
  } else {
    return <div>로그인</div>;
  }

  // return (
  //   <>
  //     {user.isLogin ? (
  //       <div>로그아웃</div>
  //     ) : (
  //       <div>로그인</div>
  //     )}
  //   </>
  // );
};

export default Main;

 

5.4) Props로 데이터 전달하기

// Props : 부모 -> 자식에게 값을 전달할 수 있음!!!

import "./App.css";
import Header from "./components/Header";
import Main from "./components/Main";
import Footer from "./components/Footer";
import Button from "./components/Button";

function App() {
  const buttonProps = { // 객체!!!
    text: "메일",
    color: "red",
    a: 1,
    b: 2,
    c: 3,
  };
  return (
    <>
      <Button {...buttonProps} /> // 스프레드 연산자!!! (값 그대로 가져오기)
      <Button text={"카페"} />
      <Button text={"블로그"}>
        <Header /> // children으로 넘어감!!!
      </Button>
    </>
  );
}

export default App;
// 구조분해할당 (undefined에러 주의 : 기본값 설정)
// children : 자식 컴포넌트의 값 넘어옴!!!

const Button = ({ text, color="black", children }) => { 
  return (
    <button style={{ color: color }}>
      {text} - {color.toUpperCase()} 
      {children}
    </button>
  );
};

export default Button;

 

5.5) 이벤트 처리하기

const Button = ({ text, color, children }) => {
  // 이벤트 객체
  const onClickButton = (e) => { // e는 이벤트 객체 : 통합된 규격의 이벤트 객체
    console.log(e);
    console.log(text);
  };

  return (
    <button
      onClick={onClickButton}
      // onMouseEnter={onClickButton} // 마우스 오버시 동작
      style={{ color: color }}
    >
      {text} - {color.toUpperCase()}
      {children}
    </button>
  );
};

Button.defaultProps = {
  color: "black",
};

export default Button;

 

5.6) State로 상태관리하기

import "./App.css";
import { useState } from "react";

// state를 사용하는 이유 : 일반변수는 변경이 생겨도 리랜더링 되지 않기때문!!!
function App() {
  const [count, setCount] = useState(0); // 구조분해할당방식
  const [light, setLight] = useState("OFF");

  return ( // 리랜더링됨.
    <>
      <div>
        <h1>{light}</h1>
        <button
          onClick={() => {
            setLight(light === "ON" ? "OFF" : "ON");
            // setState(state +1); // 1씩 증가
          }}
        >
          {light === "ON" ? "끄기" : "켜기"}
        </button>
      </div>
      <div>
        <h1>{count}</h1>
        <button
          onClick={() => {
            setCount(count + 1);
          }}
        >
          +
        </button>
      </div>
    </>
  );
}

export default App;

 

5.7) State와 Props

- [리랜더링 되는 상황]

1. 자신의 state가 변경되었을때

2. 자신의 props가 변경되었을때

3. 부모 컴포넌트가 리랜더링되었을때

import "./App.css";
import Bulb from "./components/Bulb";
import Counter from "./components/Counter";

function App() {
  return (
    <>
      <Bulb />
      <Counter />
    </>
  );
}

export default App;
import { useState } from "react";

const Bulb = () => { // 부모로 부터받은 Props가 변경되어도 리랜더링된다!!!
  const [light, setLight] = useState("OFF");

  console.log(light);
  return (
    <div>
      {light === "ON" ? (
        <h1 style={{ backgroundColor: "orange" }}>ON</h1>
      ) : (
        <h1 style={{ backgroundColor: "gray" }}>OFF</h1>
      )}

      <button
        onClick={() => {
          setLight(light === "ON" ? "OFF" : "ON");
        }}
      >
        {light === "ON" ? "끄기" : "켜기"}
      </button>
    </div>
  );
};

export default Bulb;

 

import { useState } from "react";

const Counter = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h1>{count}</h1>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        +
      </button>
    </div>
  );
};

export default Counter;

 

5.8) State로 사용자 입력 관리하기 1

import { useState } from "react";

// 간단한 회원가입 폼
// 1. 이름
// 2. 생년월일
// 3. 국적
// 4. 자기소개

const Register = () => {
  const [name, setName] = useState("이름");
  const [birth, setBirth] = useState("");
  const [country, setCountry] = useState("");
  const [bio, setBio] = useState("");

  const onChangeName = (e) => {
    setName(e.target.value); // 값 가져오기!!!
  };

  const onChangeBirth = (e) => {
    setBirth(e.target.value);
  };

  const onChangeCountry = (e) => {
    setCountry(e.target.value);
  };

  const onChangeBio = (e) => {
    setBio(e.target.value);
  };

  return (
    <div>
      <div>
        <input
          value={name}            // input칸에 보여줌!!!
          onChange={onChangeName} // 값이 입력될때마다 동작!!!
          placeholder={"이름"}    // 입력되기전에 보여주는 임시 문구 (회색)!!!
        />
      </div>

      <div>
        <input
          value={birth}
          onChange={onChangeBirth}
          type="date"
        />
      </div>

      <div>
        <select value={country} onChange={onChangeCountry}>
          <option value=""></option>
          <option value="kr">한국</option>
          <option value="us">미국</option>
          <option value="uk">영국</option>
        </select>
        {country}
      </div>

      <div>
        <textarea value={bio} onChange={onChangeBio} />
      </div>
    </div>
  );
};

export default Register;

 

5.9) State로 사용자 입력 관리하기

import { useState } from "react";
// 간단한 회원가입 폼
// 1. 이름
// 2. 생년월일
// 3. 국적
// 4. 자기소개

const Register = () => {
  const [input, setInput] = useState({
    name: "",
    gender: "",
    bio: "",
  });

  const onChange = (e) => {
    console.log(e.target.name + " : " + e.target.value);
    setInput({
      ...input, // 스프레드 연산자 (관련없는값 변경하지 않고 그대로 유지)!!!
      [e.target.name]: e.target.value,
    });
  };

  return (
    <div>
      <div>
        <input
          name="name"
          value={input.name}
          onChange={onChange}
          placeholder={"이름"}
        />
      </div>

      <div>
        <input
          name="birth"
          value={input.birth}
          onChange={onChange}
          type="date"
        />
      </div>

      <div>
        <select
          name="country"
          value={input.country}
          onChange={onChange}
        >
          <option value=""></option>
          <option value="kr">한국</option>
          <option value="us">미국</option>
          <option value="uk">영국</option>
        </select>
      </div>

      <div>
        <textarea
          name="bio"
          value={input.bio}
          onChange={onChange}
        />
      </div>
    </div>
  );
};

export default Register;

 

5.10) useRef로 컴포넌트의 변수 생성하기

- useRef : 해당 컴포넌트가 리랜더링 되더라도 특수한 경우로 값이 초기화 되지 않음.

- 일반변수 : 해당 컴포넌트가 리랜더링되면, 초기화도 같이 일어나 값이 유지될 수 없음.

   -> 컴포넌트를 두번 호출한것은 함수만 호출한것으로, 전역변수로 선언되어있는 변수는

        2개의 컴포넌트에서 같이 사용하게 된다. (의도와 다름)

import { useState, useRef } from "react";

// 간단한 회원가입 폼
// 1. 이름
// 2. 생년월일
// 3. 국적
// 4. 자기소개

const Register = () => {
  const [input, setInput] = useState({
    name: "",
    birth: "",
    country: "",
    bio: "",
  });
  const countRef = useRef(0);
  const inputRef = useRef(); // 값이 변경되어도 리랜더링되지 않음!!!

  const onChange = (e) => { 
    // countRef.current++; // 값이 변경되어도 리랜더링되지 않음!!!
    count++;
    console.log(count);
    setInput({
      ...input,
      [e.target.name]: e.target.value,
    });
  };

  const onSubmit = () => {
    if (input.name === "") {
      inputRef.current.focus();  // 이름을 입력하는 DOM 요소(HTML태그?) 포커스!!!
    }
  };

  return (
    <div>
      <div>
        <input
          ref={inputRef} // REF값 저장!!!
          name="name"
          value={input.name}
          onChange={onChange}
          placeholder={"이름"}
        />
      </div>

      <div>
        <input
          name="birth"
          value={input.birth}
          onChange={onChange}
          type="date"
        />
      </div>

      <div>
        <select
          name="country"
          value={input.country}
          onChange={onChange}
        >
          <option value=""></option>
          <option value="kr">한국</option>
          <option value="us">미국</option>
          <option value="uk">영국</option>
        </select>
      </div>

      <div>
        <textarea
          name="bio"
          value={input.bio}
          onChange={onChange}
        />
      </div>

      <button onClick={onSubmit}>제출</button>
    </div>
  );
};

export default Register;

 

5.11) React Hooks

import { useState } from "react";

function useInput() {  // 커스텀 Hooks!!!
  const [input, setInput] = useState("");

  const onChange = (e) => {
    setInput(e.target.value);
  };

  return [input, onChange]; // 구조분해할당!!!
}

export default useInput;

 

import useInput from "./../hooks/useInput";

// 3가지 hook 관련된 팁
// 1. 함수 컴포넌트, 커스텀 훅 내부에서만 호출 가능
// 2. 조건부로 호출될 수는 없다 (호출순서가 엉망이 될 수 있음!!!)
// 3. 나만의 훅(Custom Hook) 직접 만들 수 있다.

const HookExam = () => {
  const [input, onChange] = useInput();
  const [input2, onChange2] = useInput();

  return (
    <div>
      <input value={input} onChange={onChange} />
      <input value={input2} onChange={onChange2} />
    </div>
  );
};

export default HookExam;
728x90
반응형

'[강의] > [한 입 크기로 잘라 먹는 리액트(React.js)]' 카테고리의 다른 글

섹션8. 라이프사이  (0) 2025.04.02
섹션7. 프로젝트1. 카운터  (0) 2025.04.02
섹션5. React.js 개론  (0) 2025.03.28
섹션4. Node.js 기초  (0) 2025.03.26
섹션3. JavaScript 심화  (0) 2025.03.21
Comments