React - State, Hook

조영래·2024년 7월 24일
0
post-thumbnail
post-custom-banner

State

state는 간단하게 말해서 변수이다. 하지만 const, let 등으로 선언한 변수와 다르게 값이 변하면 관련 있는 컴포넌트들이 재렌더링되어 화면이 바뀐다.
state는 컴포넌트의 내부에서 변경 가능한 데이터를 다루기 위해 사용하는 객체이다.
일반적으로 리액트에서는 유동적인 데이터는 변수에 담아서 사용하지 않고 useState()라는 리액트 함수를 사용하여 state라는 저장 공간에 담아 사용한다.

useState

// App.tsx
// 이미지 클릭시 사진 On,Off 변경
import { useState } from "react";
import on from "./assets/images/b_on.png";
import off from "./assets/images/b_off.png";
const App = () => {
  const [turnOn, setTurnOn] = useState(true);
  const toggleImage = () => {
    setTurnOn(!turnOn);
  };
  return (
    <>
      <img src={turnOn ? on : off} alt="toggle" onClick={toggleImage} />
    </>
  );
};
export default App;
// input창에 색깔정보를 입력하면 div창에 background-color 변경
import { useState } from "react";
const ColorBox = () => {
  const [color, setColor] = useState("");
  const handleColorChange = (e) => {
    setColor(e.target.value);
  };
  return (
    <>
      <div className="item-middle">
        <div className="flex flex-col">
          <div
            className="w-40 h-40 border border-slate-500"
            style={{ background: color }}>
          </div>
          <input
            value={color}
            type="text"
            className="border border-slate-500 w-40 mt-2"
            onChange={handleColorChange}
          />
        </div>
      </div>
    </>
  );
};
export default ColorBox;
// input창에 로그인 
import { useRef, useState } from "react";
import Button from "../../html/Button";
import CheckBox from "../../html/CheckBox";
import Input from "../../html/Input";
const Login = () => {
  const [type, setType] = useState("Sign"); // Sign or Login
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [agree, setAgree] = useState(false);
  const nameEl = useRef<HTMLInputElement>(null);
  const emailEl = useRef<HTMLInputElement>(null);
  const passwordEl = useRef<HTMLInputElement>(null);
  const onSubmitHandler = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const loginValid = email.trim() === "" || password.trim() === "" || !agree;
    const signValid = loginValid || name.trim() === "";
    if ((type === "Login" && loginValid) || (type === "Sign" && signValid)) {
      alert("입력값 빔");
      return;
    }
    alert(type === "Sign" ? "Signup Success" : "Login Success");
  };
  return (
    <>
          <form className="flex flex-col gap-4" onSubmit={onSubmitHandler}>
            {type === "Sign" && (
              <Input
                ref={nameEl}
                type="text"
                placeholder="Enter Your Name"
                value={name}
                onChange={(e) => setName(e.target.value)}
              />
            )}
           // setAgree prev 클릭시 check or no
            <CheckBox
              checked={agree}
              onToggle={() => setAgree((prev) => !prev)}
            />
            <div className="flex flex-col gap-4 mt-4">
              <Button type="submit" className="bg-[#4F4F4F]">
                {type === "Sign" ? "Sign In" : "Log In"}
              </Button>
              <Button
                type="button"
                className="border border-[#4F4F4F] text-[#4F4F4F]"
                onClick={() => {
                  setName("");
                  setEmail("");
                  setPassword("");
                  setType((prev) => (prev === "Login" ? "Sign" : "Login"));
                }}

              </Button>
            </div>
          </form>
    </>
  );
};
export default Login;
// 함수로 따로 만들어서 사용
const handleChange = (e) => {
   setText(e.target.value); 
 };
// 태그 안에서 바로 사용할수있음
<input onChange={(e) => setText(e.target.value)} />
// 클릭이벤트 만들때 prev로 이전꺼로 눌렀다 !prev 부정으로 만들어서 on/off 상태변경
onClick={() => setAgree((prev) => !prev)}

useRef

useRef는 저장공간 또는 DOM요소에 접근하기 위해 사용되는 React Hook이seRef는 저장공간 또는 DOM요소에 접근하기 위해 사용되는 React Hook이다

import { useRef, useState } from "react";
import Login from "./components/Login";
// useRef가 하나의 dom객체를 연결할수있다
const App = () => {};
export default App;
const count = useRef(0);
{
  <h1>count.current</h1>
}
// useRef로 만든건 항상 current 속성으로 접근해야한다
// component에서 값을 유지하고 싶을때 사용
interface Todo {
  id: number;
  text: string;
}
const count = useRef(0);
  const [arr, setArr] = useState<number[]>([]);
  const onClickHandler = () => {
    count.current += 1;
    setArr((prev) => [...prev, count.current]);
  };
  return (
     <>
       <pre>{JSON.stringify(arr)}</pre>
       <button onClick={onClickHandler}>할일추가</button>
     </>
   )

조건부 렌더링

import { ListItem } from "./ListItem";
const App = () => {
  const isLoggedin = false;
  //조건부 렌더링
  if (isLoggedin) {
    return <h1>Logged In Successful</h1>;
  }
// 삼항 연산자
{isLoggedin ? <h1>Logged In Succesful</h1> : <h1>Login Failed</h1>}
// 논리 연산자
{isLoggedin && <h1>Logged In Successful</h1>}
{!isLoggedin && <h1>Logged In Failed</h1>}
 // 즉시 실행 함수
  {(() => {
    if (isLoggedin) {
      <h1>Logged In Successful</h1>;
    }
    return <h1>Logged In Failed</h1>;
  })()}
//반복 렌더링 map 이용해서
const fruits = ["apple", "banana", "cherry"];
 {<fruits.map((fruit, abc) => (
    <li key={abc}>{fruit}</li>
 ))}
//component로 받아오기
  <ul>
     {users.map(({ name, age }) => (
        <li>
          <ListItem key={name} name={name} age={age} />
        </li>
      ))}
  </ul> 

이미지 불러오는 법

// App.tsx
import mark from "./assets/images/react.png";
const App = () => {
  return (
    <>
      //import해서 불러오는방법
        <img src={mark} alt="" />
     // css로 불러오는 방법
        <div className="bg-img w-[300px] h-[300px] bg-cover"></div>
    </>
  );
};
export default App;
// css로 불러오는 방법에서 사용할때 css내용
.bg-img {
  background-image: url("./assets/images/react.png");
}

profile
난될놈이야
post-custom-banner

0개의 댓글