본문 바로가기

카테고리 없음

React_240506 (State , Props , useRef , Hooks)

State와Props 활용

import "./App.css";
import { useState } from "react";
import Bulb from "./components/Bulb";
import Counter from "./components/Counter";
//함수 컴포넌트 리랜더링 -> App함수 재호출하고 바뀐 값을 재랜더링
//자신이 관리하는 state 값 변경시 , 자신이 제공 받는 props값이 변경시
//부모 component 리랜더링시 자신도 리랜더링 -> 위 3가지 경우 리랜더링

// 컴포넌트를 나누어 불필요한 리랜더링 방지
function App() {
  return (
    <>
      <Bulb />
      <Counter />
    </>
  );
}

export default App;

 

import { useState } from "react";

const Bulb = () => {
  //[state값 , 변경시킬 함수]
  const [light, setLight] = useState("off");
  // let light="off"
  return (
    <div>
      {light === "on" ? (
        <h1 style={{ backgroundColor: "orange" }}>on</h1>
      ) : (
        <h1 style={{ backgroundColor: "gray" }}>off</h1>
      )}
      <div>
        <button
          onClick={() => {
            setLight(light === "on" ? "off" : "on");

            // 스테이트의 상태가 변한게 아니므로 리랜더링X
            // light = light === "on" ? "off" : "on";
          }}
        >
          {light === "on" ? "끄기" : "켜기"}
        </button>
      </div>
    </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;

 

 

단순 활용

import { useState } from "react";
//간단한 회원가입 폼
//이름 , 생년월일 , 국적 , 자기소개
//State를 이용한 저장법
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의 값이 변경 되었을 때 : onChange
      placeholder : 인풋 내부에 흐린 글씨로 표시
      value는 onchange내 함수 호출시 state의 name에 값 저장*/}
        <input value={name} 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;

 

State및 EventHandler효율적으로 통합

 

import { useState } from "react";
//간단한 회원가입 폼
//이름 , 생년월일 , 국적 , 자기소개
//State를 이용한 저장법
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 onChangeName = (e) => {
  //     setInput({
  //       //...input 스프레드 연산자로 다른 프로퍼티(속성) 값들을 그대로 유지 가능
  //       //누락시 다른 속성들이 사라져버림
  //       ...input,
  //       name: e.target.value,
  //     });
  //   };
  //   console.log(input);

  //State를 객체로 만들어 통합하여 관리
  const [input, setInput] = useState({
    name: "",
    birth: "",
    country: "",
    bio: "",
  });

  //4개의 이벤트 핸들러 압축 (통합 핸들러)
  //onChange함수 실행 -> setInput 상태변화 함수 호출 -> 인수로 객체를 만들어저장
  //스프레드 연산자로 input값 나열 -> 프로퍼티 키 명시 위치에 ([여기])
  //여기에 변수의 이름을 기재시 값이 프로퍼티 키로 설정가능
  const onChange = (e) => {
    //e.target.name은 아래 birth bio등 값이 들어감
    console.log(e.target.name, e.target.value);
    setInput({
      ...input,
      [e.target.name]: e.target.value,
    });
  };

  return (
    <div>
      <div>
        {/* input의 값이 변경 되었을 때 : onChange
      placeholder : 인풋 내부에 흐린 글씨로 표시
      value는 onChange내 함수 호출시 state의 name에 값 저장
      name은 핸들러 타겟의 이름 설정 */}
        <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;

 

useRef 추가 적용

import { useState, useRef } from "react";
//간단한 회원가입 폼
//이름 , 생년월일 , 국적 , 자기소개
//State를 이용한 저장법
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 onChangeName = (e) => {
  //     setInput({
  //       //...input 스프레드 연산자로 다른 프로퍼티(속성) 값들을 그대로 유지 가능
  //       //누락시 다른 속성들이 사라져버림
  //       ...input,
  //       name: e.target.value,
  //     });
  //   };
  //   console.log(input);

  //State를 객체로 만들어 통합하여 관리
  //useState 리랜더링 되더라도 리셋되지않고 유지
  const [input, setInput] = useState({
    name: "",
    birth: "",
    country: "",
    bio: "",
  });

  //reference는 state와 비슷하지만 리랜더링X
  const countRef = useRef(0);
  const inputRef = useRef();
  //Register컴포넌트가 계속 리랜더링 되면서 전체를 재호출하므로 count=1이 고정
  //전역으로 설정하면 영향을 받진 않지만 App.jsx에서 Register컴포넌트를
  //여러번 호출시 컴포넌트간 전역변수를 공유하므로 바람직하지않음
  //필요하다면 useRef를 활용하는게 좋음
  let count = 0;

  //4개의 이벤트 핸들러 압축 (통합 핸들러)
  //onChange함수 실행 -> setInput 상태변화 함수 호출 -> 인수로 객체를 만들어저장
  //스프레드 연산자로 input값 나열 -> 프로퍼티 키 명시 위치에 ([여기])
  //여기에 변수의 이름을 기재시 값이 프로퍼티 키로 설정가능
  const onChange = (e) => {
    //e.target.name은 아래 birth bio등 값이 들어감
    // console.log(e.target.name, e.target.value);

    // countRef.current++;
    count++;
    console.log(count);
    setInput({
      ...input,
      [e.target.name]: e.target.value,
    });
  };

  const onSubmit = () => {
    if (input.name === "") {
      //이름을 입력하는 DOM 요소 포커스(선택된 상태)
      //console.log(inputRef.current);
      inputRef.current.focus();
    }
  };

  return (
    <div>
      <div>
        {/* input의 값이 변경 되었을 때 : onChange
      placeholder : 인풋 내부에 흐린 글씨로 표시
      value는 onChange내 함수 호출시 state의 name에 값 저장
      name은 핸들러 타겟의 이름 설정 */}
        <input
          ref={inputRef}
          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;

 

Hook 추가

 

import useInput from "../hooks/useInput";
// 훅 : classComponent의 기능을 functionComponent에서도 사용가능하도록 끌어오는 것
// 종류가 20가지정도로 상당히 많음 -> useState , useRef등도 여기 포함됨
import { useState } from "react";
// 훅은 반드시 함수 컴포넌트or커스텀 훅 내부에서만 호출 가능
// 조건부로 호출 될 수는 없다 -> 조건문이나 반복문 안에서 호출 할 수 없다.
// ->컴포넌트를 호출하여 랜더링시 서로 다른 훅의 순서가 꼬일 수 있어 막아뒀다.
// 개발자가 임의로 만드는 customHook을 직접 만들 수 있다

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;

 

import { useState } from "react";
//훅은 컴포넌트 와 별개로 훅 폴더에 따로 저장해주는게 좋음
//커스텀 훅 : 함수명앞에use를 붙여주면 훅으로 인식함
function useInput() {
  const [input, setInput] = useState("");

  const onChange = (e) => {
    setInput(e.target.value);
  };
  return [input, onChange];
}

export default useInput;